This is the code for the statistical analysis for “Vowel Acoustics as Predictors of Speech Intelligibility in Dysarthria.”

Loading Packages


library(rio)
library(tidyverse)
library(irr) # install.packages('irr')
library(performance)
library(car)
library(ggpubr)
library("Hmisc") # install.packages('Hmisc')
library(ggridges)
library(furniture) # install.packages('furniture')
library(gt)
library(patchwork)
library(ks)
library(emuR) # install.packages('emuR')
library(geomtextpath) # remotes::install_github("AllanCameron/geomtextpath")

Upload Datasets


Reliability <- rio::import("Prepped Data/Reliability Data.csv")
AcousticData <- rio::import("Prepped Data/AcousticMeasures.csv") %>%
  dplyr::mutate(intDiff = VAS - transAcc)

AcousticData <- AcousticData %>%
  dplyr::filter(!grepl("_rel", Speaker)) %>%
  dplyr::select(c(Speaker, Sex, Etiology, vowel_ED_b, VSA_b, Hull_b, Hull_bVSD_25, Hull_bVSD_50, Hull_bVSD_75, VAS, transAcc)) %>%
  dplyr::mutate(Etiology = as.factor(Etiology),
                Sex = as.factor(Sex),
                Speaker = as.factor(Speaker))

Listeners <- rio::import("Prepped Data/Listener_Demographics.csv") %>%
  dplyr::select(!c(StartDate:proloficID, Q2.4_6_TEXT, Q3.2_8_TEXT, AudioCheck:EP3))

Listeners$race[Listeners$Q3.3_7_TEXT == "Native American/ African amercing"] <- "Biracial or Multiracial"

Inter-rater Reliability

Two raters (the first two authors) completed vowel segmentation for the speakers. To calculate inter-rater reliability, 20% of the speakers were segmented again by the other rater. Two-way intraclass coefficients were computed for the extracted F1 and F2 from the temporal midpoint of the vowel segments. Since only one set of ratings will be used in the data analysis, we focus on the single ICC results and interpretation. However, we also report the average ICC values to be comprehensive.


## Creating new data frames to calculate ICC for extracted F1 and F2 values

F1_Rel <- Reliability %>%
  dplyr::select(c(F1, F1_rel))

F2_Rel <- Reliability %>%
  dplyr::select(c(F2, F2_rel))
  
## Single ICC for F1
Single_F1 <- irr::icc(F1_Rel, model = "twoway", type = "agreement", unit = "single")

## Average ICC for F1
Average_F1 <- irr::icc(F1_Rel, model = "twoway", type = "agreement", unit = "average")

## Single ICC for F2
Single_F2 <- irr::icc(F2_Rel, model = "twoway", type = "agreement", unit = "single")

## Average ICC for F2
Average_F2 <- irr::icc(F2_Rel, model = "twoway", type = "agreement", unit = "average")

## Inter-rater reliability results and interpretation

print(paste("Single ICC for F1 is ", round(Single_F1$value, digits = 3), ". ", 
            "The 95% CI is [", round(Single_F1$lbound, digits = 3), " - ", round(Single_F1$ubound, digits = 3), "].", sep = ""))
[1] "Single ICC for F1 is 0.866. The 95% CI is [0.837 - 0.89]."
print(paste("Single ICC for F2 is ", round(Single_F2$value, digits = 3), ". ", 
            "The 95% CI is [", round(Single_F2$lbound, digits = 3), " - ", round(Single_F2$ubound, digits = 3), "].", sep = ""))
[1] "Single ICC for F2 is 0.931. The 95% CI is [0.916 - 0.944]."
print(paste("Average ICC for F1 is ", round(Average_F1$value, digits = 3), ". ", 
            "The 95% CI is [", round(Average_F1$lbound, digits = 3), " - ", round(Average_F1$ubound, digits = 3), "].", sep = ""))
[1] "Average ICC for F1 is 0.928. The 95% CI is [0.911 - 0.942]."
print(paste("Average ICC for F2 is ", round(Average_F2$value, digits = 3), ". ", 
            "The 95% CI is [", round(Average_F2$lbound, digits = 3), " - ", round(Average_F2$ubound, digits = 3), "].", sep = ""))
[1] "Average ICC for F2 is 0.964. The 95% CI is [0.956 - 0.971]."
print("Thus, interrater reliability for the extracted F1 and F2 values from the vowel segments was good to excellent.")
[1] "Thus, interrater reliability for the extracted F1 and F2 values from the vowel segments was good to excellent."
## Removing extra data frames from environment

rm(F1_Rel, F2_Rel, Reliability, Single_F1, Single_F2, Average_F1, Average_F2)

Descriptive Statistics

Correlations

CorrMatrix <- AcousticData %>%
  dplyr::select(VSA_b, vowel_ED_b, Hull_b, Hull_bVSD_25, Hull_bVSD_50, Hull_bVSD_75, VAS, transAcc) %>%
  as.matrix() %>%
  Hmisc::rcorr()

CorrMatrix <- CorrMatrix$r

stats::cor.test(AcousticData$VSA_b, AcousticData$vowel_ED_b, method = "pearson")

    Pearson's product-moment correlation

data:  AcousticData$VSA_b and AcousticData$vowel_ED_b
t = 6.5285, df = 38, p-value = 1.076e-07
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.5372669 0.8468014
sample estimates:
      cor 
0.7270881 
stats::cor.test(AcousticData$Hull_b, AcousticData$Hull_bVSD_25, method = "pearson")

    Pearson's product-moment correlation

data:  AcousticData$Hull_b and AcousticData$Hull_bVSD_25
t = 9.4906, df = 38, p-value = 1.43e-11
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.7135136 0.9119080
sample estimates:
     cor 
0.838625 
write.csv(CorrMatrix, file = "Tables/Correlation Matrix.csv")
rm(CorrMatrix)

Research Q1: Modeling Intelligibility

Orthographic Transcriptions

Model 1


# Specifying Model 1

OT_Model1 <- lm(transAcc ~ Hull_bVSD_25, data = AcousticData)

## Model 1 Assumptions 

performance::check_model(OT_Model1)


## Model 1 Summary

summary(OT_Model1)

Call:
lm(formula = transAcc ~ Hull_bVSD_25, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.896 -14.090   5.996  17.470  36.105 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   48.2973     9.7372   4.960  1.5e-05 ***
Hull_bVSD_25   0.6417     0.5663   1.133    0.264    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.83 on 38 degrees of freedom
Multiple R-squared:  0.03268,   Adjusted R-squared:  0.007224 
F-statistic: 1.284 on 1 and 38 DF,  p-value: 0.2643

Model 2


## Specifying Model 2

OT_Model2 <- lm(transAcc ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

## Model 2 Assumption Check

performance::check_model(OT_Model2)


## Model 2 Summary

summary(OT_Model2)

Call:
lm(formula = transAcc ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-48.854 -13.962   5.567  16.758  36.257 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   47.3374    10.3316   4.582 5.09e-05 ***
Hull_bVSD_25   0.8045     0.7781   1.034    0.308    
Hull_bVSD_75  -0.7188     2.3225  -0.309    0.759    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.11 on 37 degrees of freedom
Multiple R-squared:  0.03518,   Adjusted R-squared:  -0.01698 
F-statistic: 0.6745 on 2 and 37 DF,  p-value: 0.5156
## Model 1 and Model 2 Comparison

anova(OT_Model1, OT_Model2)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_25
Model 2: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     38 21570                           
2     37 21514  1    55.696 0.0958 0.7587

Model 3


## Specifying Model 3

OT_Model3 <- lm(transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(OT_Model3)


## Model 3 Summary

summary(OT_Model3)

Call:
lm(formula = transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, 
    data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-56.706 -13.157   7.018  17.957  29.990 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   31.0806    14.4916   2.145   0.0388 *
Hull_bVSD_25  -0.8439     1.2984  -0.650   0.5199  
Hull_bVSD_75   0.3159     2.3714   0.133   0.8948  
Hull_b         1.2941     0.8247   1.569   0.1253  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.65 on 36 degrees of freedom
Multiple R-squared:  0.09695,   Adjusted R-squared:  0.0217 
F-statistic: 1.288 on 3 and 36 DF,  p-value: 0.2932
## Model 2 and Model 3 Comparison

anova(OT_Model2, OT_Model3)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75
Model 2: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     37 21514                           
2     36 20137  1    1377.5 2.4626 0.1253

Model 4


## Specifying Model 4

OT_Model4 <- lm(transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(OT_Model4)


## Model 4 Summary

summary(OT_Model4)

Call:
lm(formula = transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + 
    VSA_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-44.796 -11.144   3.042  12.567  34.297 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   27.4533    13.1156   2.093  0.04365 * 
Hull_bVSD_25  -1.2602     1.1782  -1.070  0.29214   
Hull_bVSD_75   0.5663     2.1390   0.265  0.79274   
Hull_b         0.7364     0.7654   0.962  0.34261   
VSA_b          6.0896     1.9954   3.052  0.00432 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.32 on 35 degrees of freedom
Multiple R-squared:  0.2868,    Adjusted R-squared:  0.2052 
F-statistic: 3.518 on 4 and 35 DF,  p-value: 0.01626
## Model 3 and Model 4 Comparison

anova(OT_Model3, OT_Model4)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b
Model 2: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b
  Res.Df   RSS Df Sum of Sq     F   Pr(>F)   
1     36 20137                               
2     35 15904  1    4232.4 9.314 0.004321 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 5


## Specifying Model 5

OT_Model5 <- lm(transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b + vowel_ED_b, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(OT_Model5)


## Model 4 Summary

summary(OT_Model5)

Call:
lm(formula = transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + 
    VSA_b + vowel_ED_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-46.533 -11.028   3.327  13.017  33.227 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   20.3598    21.5072   0.947   0.3505  
Hull_bVSD_25  -1.2567     1.1924  -1.054   0.2994  
Hull_bVSD_75   0.7007     2.1882   0.320   0.7508  
Hull_b         0.6895     0.7826   0.881   0.3845  
VSA_b          5.3903     2.6194   2.058   0.0473 *
vowel_ED_b     5.5182    13.1650   0.419   0.6777  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.57 on 34 degrees of freedom
Multiple R-squared:  0.2904,    Adjusted R-squared:  0.1861 
F-statistic: 2.783 on 5 and 34 DF,  p-value: 0.03271
## Model 3 and Model 4 Comparison

anova(OT_Model4, OT_Model5)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b
Model 2: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b + vowel_ED_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     35 15904                           
2     34 15823  1    81.764 0.1757 0.6777

Final Model


## Specifying Final Model

OT_Model_final <- lm(transAcc ~ VSA_b, data = AcousticData)

## Final Model Assumption Check

performance::check_model(OT_Model_final)


## Final Model Summary

summary(OT_Model_final)

Call:
lm(formula = transAcc ~ VSA_b, data = AcousticData)

Residuals:
   Min     1Q Median     3Q    Max 
-46.72 -12.69   2.97  14.37  35.39 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   32.508      7.857   4.138 0.000187 ***
VSA_b          5.872      1.613   3.641 0.000807 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 20.86 on 38 degrees of freedom
Multiple R-squared:  0.2586,    Adjusted R-squared:  0.2391 
F-statistic: 13.25 on 1 and 38 DF,  p-value: 0.0008068
confint(OT_Model_final)
                2.5 %    97.5 %
(Intercept) 16.602765 48.413532
VSA_b        2.606927  9.137097

VAS Models

Model 1


# Specifying Model 1

VAS_Model1 <- lm(VAS ~ Hull_bVSD_25, data = AcousticData)

## Model 1 Assumptions 

performance::check_model(VAS_Model1)


## Model 1 Summary

summary(VAS_Model1)

Call:
lm(formula = VAS ~ Hull_bVSD_25, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.625 -16.684   8.462  19.440  37.352 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   42.6328    10.7512   3.965 0.000313 ***
Hull_bVSD_25   0.5877     0.6253   0.940 0.353236    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.31 on 38 degrees of freedom
Multiple R-squared:  0.02272,   Adjusted R-squared:  -0.003001 
F-statistic: 0.8833 on 1 and 38 DF,  p-value: 0.3532

Model 2


## Specifying Model 2

VAS_Model2 <- lm(VAS ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

## Model 2 Assumption Check

performance::check_model(VAS_Model2)


## Model 2 Summary

summary(VAS_Model2)

Call:
lm(formula = VAS ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.850 -16.576   8.382  19.448  37.237 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   42.3384    11.4211   3.707 0.000684 ***
Hull_bVSD_25   0.6376     0.8602   0.741 0.463195    
Hull_bVSD_75  -0.2204     2.5674  -0.086 0.932036    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.66 on 37 degrees of freedom
Multiple R-squared:  0.02291,   Adjusted R-squared:  -0.0299 
F-statistic: 0.4338 on 2 and 37 DF,  p-value: 0.6513
## Model 1 and Model 2 Comparison

anova(VAS_Model1, VAS_Model2)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_25
Model 2: VAS ~ Hull_bVSD_25 + Hull_bVSD_75
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     38 26296                           
2     37 26291  1     5.239 0.0074  0.932

Model 3


## Specifying Model 3

VAS_Model3 <- lm(VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(VAS_Model3)


## Model 3 Summary

summary(VAS_Model3)

Call:
lm(formula = VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-56.444 -18.989   6.121  18.036  32.281 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept)   25.0400    16.0599   1.559    0.128
Hull_bVSD_25  -1.1164     1.4389  -0.776    0.443
Hull_bVSD_75   0.8805     2.6280   0.335    0.740
Hull_b         1.3770     0.9139   1.507    0.141

Residual standard error: 26.21 on 36 degrees of freedom
Multiple R-squared:  0.08087,   Adjusted R-squared:  0.00428 
F-statistic: 1.056 on 3 and 36 DF,  p-value: 0.3799
## Model 2 and Model 3 Comparison

anova(VAS_Model2, VAS_Model3)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_25 + Hull_bVSD_75
Model 2: VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     37 26291                           
2     36 24731  1    1559.6 2.2702 0.1406

Model 4


## Specifying Model 4

VAS_Model4 <- lm(VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(VAS_Model4)


## Model 4 Summary

summary(VAS_Model4)

Call:
lm(formula = VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b, 
    data = AcousticData)

Residuals:
   Min     1Q Median     3Q    Max 
-42.25 -14.17   5.76  16.26  41.48 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   21.0802    14.5922   1.445  0.15746   
Hull_bVSD_25  -1.5708     1.3109  -1.198  0.23885   
Hull_bVSD_75   1.1539     2.3798   0.485  0.63078   
Hull_b         0.7682     0.8516   0.902  0.37320   
VSA_b          6.6479     2.2200   2.995  0.00502 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.72 on 35 degrees of freedom
Multiple R-squared:  0.2683,    Adjusted R-squared:  0.1847 
F-statistic: 3.209 on 4 and 35 DF,  p-value: 0.02405
## Model 3 and Model 4 Comparison

anova(VAS_Model3, VAS_Model4)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b
Model 2: VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b
  Res.Df   RSS Df Sum of Sq      F  Pr(>F)   
1     36 24731                               
2     35 19687  1    5043.9 8.9671 0.00502 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 5


## Specifying Model 5

VAS_Model5 <- lm(VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b + vowel_ED_b, data = AcousticData)

## Model 5 Assumption Check

performance::check_model(VAS_Model5)


## Model 5 Summary

summary(VAS_Model5)

Call:
lm(formula = VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b + 
    vowel_ED_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-44.569 -13.697   5.187  16.183  40.204 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   12.6419    23.9197   0.529   0.6006  
Hull_bVSD_25  -1.5667     1.3261  -1.181   0.2456  
Hull_bVSD_75   1.3137     2.4337   0.540   0.5928  
Hull_b         0.7124     0.8704   0.818   0.4188  
VSA_b          5.8159     2.9132   1.996   0.0539 .
vowel_ED_b     6.5644    14.6417   0.448   0.6568  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.99 on 34 degrees of freedom
Multiple R-squared:  0.2726,    Adjusted R-squared:  0.1657 
F-statistic: 2.549 on 5 and 34 DF,  p-value: 0.0461
## Model 4 and Model 5 Comparison

anova(VAS_Model4, VAS_Model5)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b
Model 2: VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b + VSA_b + vowel_ED_b
  Res.Df   RSS Df Sum of Sq     F Pr(>F)
1     35 19687                          
2     34 19572  1     115.7 0.201 0.6568

Final Model


## Specifying Final Model

VAS_Model_final <- lm(VAS ~ VSA_b, data = AcousticData)

## Final Model Assumption Check

performance::check_model(VAS_Model_final)


## Final Model Summary

summary(VAS_Model_final)

Call:
lm(formula = VAS ~ VSA_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-44.956 -15.943   6.754  17.153  43.062 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)   24.703      8.761   2.820  0.00760 **
VSA_b          6.163      1.798   3.427  0.00148 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.26 on 38 degrees of freedom
Multiple R-squared:  0.2361,    Adjusted R-squared:  0.216 
F-statistic: 11.74 on 1 and 38 DF,  p-value: 0.001482
confint(VAS_Model_final)
               2.5 %    97.5 %
(Intercept) 6.966936 42.438084
VSA_b       2.521887  9.803467

Research Q2: Relationship between OT and VAS

Model 1


# Specify Model

OT_VAS_model <- lm(transAcc ~ VAS*Etiology + VAS*Sex, data = AcousticData)

# Assumption Check

performance::check_model(OT_VAS_model)


# Model Results

summary(OT_VAS_model)

Call:
lm(formula = transAcc ~ VAS * Etiology + VAS * Sex, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-14.910  -4.525  -1.280   5.529  16.932 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)        10.8993562  5.7092981   1.909   0.0659 .  
VAS                 0.8924319  0.1276625   6.991  9.1e-08 ***
EtiologyAtaxic      2.9854239  9.5149402   0.314   0.7559    
EtiologyHD          2.1009983  7.3948950   0.284   0.7783    
EtiologyPD         -2.4903757 10.1590855  -0.245   0.8080    
SexM                6.8939642  7.0796700   0.974   0.3380    
VAS:EtiologyAtaxic -0.0019088  0.1791048  -0.011   0.9916    
VAS:EtiologyHD      0.0007804  0.1453318   0.005   0.9958    
VAS:EtiologyPD      0.0320470  0.1732105   0.185   0.8545    
VAS:SexM           -0.1220661  0.1241230  -0.983   0.3333    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 8.488 on 30 degrees of freedom
Multiple R-squared:  0.9031,    Adjusted R-squared:  0.874 
F-statistic: 31.06 on 9 and 30 DF,  p-value: 8.181e-13

Final Model


# Specify Final Model

OT_VAS_final <- lm(transAcc ~ VAS, data = AcousticData)

confint(OT_VAS_final)
                2.5 %     97.5 %
(Intercept) 8.1038688 19.3870846
VAS         0.7637645  0.9580856
# Model Results

summary(OT_VAS_final)

Call:
lm(formula = transAcc ~ VAS, data = AcousticData)

Residuals:
     Min       1Q   Median       3Q      Max 
-13.6882  -4.9316  -0.4408   4.9974  17.2110 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 13.74548    2.78681   4.932 1.64e-05 ***
VAS          0.86093    0.04799  17.938  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 7.873 on 38 degrees of freedom
Multiple R-squared:  0.8944,    Adjusted R-squared:  0.8916 
F-statistic: 321.8 on 1 and 38 DF,  p-value: < 2.2e-16

Manuscript Tables

##Descriptives Table

gtData <- AcousticData %>%
  rbind(.,AcousticData %>%
          dplyr::mutate(Etiology = "All Etiologies")) %>%
  rbind(.,AcousticData %>%
          rbind(.,AcousticData %>%
          dplyr::mutate(Etiology = "All Etiologies")) %>%
          dplyr::mutate(Sex = "All")) %>%
  dplyr::mutate(Sex = as.factor(Sex),
                Etiology = as.factor(Etiology)) %>%
  dplyr::group_by(Sex, Etiology) %>%
  dplyr::summarize(VSA_mean = mean(VSA_b, na.rm =T), VSA_sd = sd(VSA_b, na.rm = T),
                   Disp_mean = mean(vowel_ED_b, na.rm =T), Disp_sd = sd(vowel_ED_b, na.rm =T),
                   Hull_mean = mean(Hull_b, na.rm =T), Hull_sd = sd(Hull_b, na.rm =T),
                   VSD25_mean = mean(Hull_bVSD_25, na.rm =T), VSD25_sd = sd(Hull_bVSD_25, na.rm =T),
                   VSD50_mean = mean(Hull_bVSD_50, na.rm =T), VSD50_sd = sd(Hull_bVSD_50, na.rm =T),
                   VSD75_mean = mean(Hull_bVSD_75, na.rm =T), VSD75_sd = sd(Hull_bVSD_75, na.rm =T),
                   VAS_mean = mean(VAS, na.rm =T), VAS_sd = sd(VAS, na.rm =T),
                   OT_mean = mean(transAcc, na.rm =T), OT_sd = sd(transAcc, na.rm =T)) %>%
  pivot_longer(cols = VSA_mean:OT_sd, names_to = "Measure",
               values_to = "Value") %>%
  dplyr::mutate(meanSD = ifelse(grepl("_mean",Measure),"M","sd"),
                Measure = gsub("_mean","",Measure),
                Measure = gsub("_sd","",Measure),
                Etiology = paste(Etiology,meanSD, sep = "_"),
                Sex = case_when(
                  Sex == "All" ~ "All Speakers",
                  Sex == "M" ~ "Male",
                  Sex == "F" ~ "Female"
                )) %>%
  dplyr::select(!meanSD) %>%
  pivot_wider(names_from = Etiology, values_from = "Value") %>%
  dplyr::filter(Measure != "VSD50")
`summarise()` has grouped output by 'Sex'. You can override using the `.groups` argument.
gtData %>%
  gt::gt(
    rowname_col = "Measure",
    groupname_col = "Sex",
  ) %>%
  fmt_number(
    columns = 'All Etiologies_M':PD_sd,
    decimals = 2
  ) %>%
  tab_spanner(
    label = "All Etiologies",
    columns = c('All Etiologies_M', 'All Etiologies_sd')
  ) %>%
    tab_spanner(
    label = "ALS",
    columns = c(ALS_M, ALS_sd)
  ) %>%
  tab_spanner(
    label = "PD",
    columns = c(PD_M, PD_sd)
  ) %>%
  tab_spanner(
    label = "HD",
    columns = c(HD_M, HD_sd)
  ) %>%
  tab_spanner(
    label = "Ataxic",
    columns = c(Ataxic_M, Ataxic_sd)
  ) %>%
  cols_label(
     'All Etiologies_M' = "M",
     'All Etiologies_sd' = "SD",
     ALS_M = "M",
     ALS_sd = "SD",
     PD_M = "M",
     PD_sd = "SD",
     HD_M = "M",
     HD_sd = "SD",
     Ataxic_M = "M",
     Ataxic_sd = "SD"
  ) %>%
  gtsave("DescriptivesTable.html", path = "Tables")

OT Model

sjPlot::tab_model(OT_Model1,OT_Model2,OT_Model3, OT_Model4, OT_Model5, OT_Model_final,
                  show.ci = F,
                  p.style = "stars",
                  file = "Tables/OT Models.html")

VAS Model

sjPlot::tab_model(VAS_Model1,VAS_Model2,VAS_Model3, VAS_Model4, VAS_Model5, VAS_Model_final,
                  show.ci = F,
                  p.style = "stars",
                  file = "Tables/VAS Models.html")

OT vs. VAS

sjPlot::tab_model(OT_VAS_model,OT_VAS_final,
                  show.ci = F,
                  show.reflvl = TRUE,
                  p.style = "stars",
                  file = "Tables/OT and VAS Comparison.html")

Manuscript Figures

Example Measures

formantColor <- "grey"
formantAlpha <- .95
lineColor <- "white"
lineAlpha <- .8

vowelData <- rio::import("Prepped Data/Vowel Data.csv") %>%
  dplyr::filter(Speaker == "AF8")

  Pitch_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = ".Pitch", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = F) %>%
    dplyr::rename(Pitch = V1) %>%
    dplyr::mutate(Pitch = gsub("--undefined--",NA,Pitch),
                  Pitch = as.numeric(Pitch))
  
  Formants_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = "_Formant", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = T) %>%
    dplyr::select(!c(nformants, B1.Hz., B2.Hz., B3.Hz., F4.Hz., B4.Hz., F5.Hz., B5.Hz.)) %>%
    dplyr::rename(Time_s = time.s.,
                  F1_Hz = F1.Hz.,
                  F2_Hz = F2.Hz.,
                  F3_Hz = F3.Hz.) %>%
    dplyr::mutate(F1_Hz = ifelse(F1_Hz == 0, NA, F1_Hz),
                  F2_Hz = ifelse(F2_Hz == 0, NA, F2_Hz),
                  F3_Hz = ifelse(F3_Hz == 0, NA, F3_Hz)) %>%
    dplyr::mutate(F1_Hz = as.numeric(F1_Hz),
                  F2_Hz = as.numeric(F2_Hz),
                  F3_Hz = suppressWarnings(as.numeric(F3_Hz)),
                  Time_ms = Time_s / 1000,
                  F1_kHz = F1_Hz / 1000,
                  F2_kHz = F2_Hz / 1000,
                  F3_kHz = F3_Hz / 1000) %>%
    dplyr::select(!Time_s) %>%
    dplyr::relocate(Time_ms, .before = F1_Hz) %>%
    cbind(.,Pitch_PRAAT)
  
  c <- 2
  while(c < NROW(Formants_PRAAT)){
    Formants_PRAAT$F1_Hz[c] <- ifelse(is.na(Formants_PRAAT$F1_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F1_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F1_Hz[c])
    Formants_PRAAT$F2_Hz[c] <- ifelse(is.na(Formants_PRAAT$F2_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F2_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F2_Hz[c])
    c <- c + 1
  }
  rm(c)
  
  Formants_PRAAT <- Formants_PRAAT %>%
    dplyr::filter(!is.na(Pitch)) %>%
    dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                  F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
    dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
    dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T))) %>%
    dplyr::filter(mDist_sd < 2) %>%
    dplyr::select(!c(F1_mad, F2_mad, mDist, mDist_sd)) %>%
    dplyr::mutate(F1_z = scale(F1_Hz, center = TRUE),
                  F2_z = scale(F2_Hz, center = TRUE),
                  F3_z = scale(F3_Hz, center = TRUE),
                  F1_b = emuR::bark(F1_Hz),
                  F2_b = emuR::bark(F2_Hz),
                  F3_b = emuR::bark(F3_Hz))
  
  rm(Pitch_PRAAT)
  
  
## Corner Dispersion ----
  wedge <- vowelData %>%
    dplyr::group_by(Vowel) %>%
    dplyr::summarize(mean_F1 = mean(F1_tempMid),
              mean_F2 = mean(F2_tempMid),
              mean_F1_z = mean(F1_z_tempMid),
              mean_F2_z = mean(F2_z_tempMid),
              mean_F1_b = mean(F1_b_tempMid),
              mean_F2_b = mean(F2_b_tempMid)) %>%
    dplyr::filter(Vowel == "v")
    
  corner_dis <- vowelData %>%
    dplyr::filter(Vowel != "v") %>%
    dplyr::group_by(Vowel) %>%
    dplyr::summarize(mean_F1 = mean(F1_tempMid),
              mean_F2 = mean(F2_tempMid),
              mean_F1_z = mean(F1_z_tempMid),
              mean_F2_z = mean(F2_z_tempMid),
              mean_F1_b = mean(F1_b_tempMid),
              mean_F2_b = mean(F2_b_tempMid)) %>%
    dplyr::mutate(Vowel_ED = sqrt((mean_F1-wedge$mean_F1)^2 + (mean_F2-wedge$mean_F2)^2),
                  Vowel_ED_z = sqrt((mean_F1_z-wedge$mean_F1_z)^2 + (mean_F2_z-wedge$mean_F2_z)^2),
                  Vowel_ED_b = sqrt((mean_F1_b-wedge$mean_F1_b)^2 + (mean_F2_b-wedge$mean_F2_b)^2))

    
# Plot Corner Dispersion
      # Changing to IPA symbols
      corner_dis <- corner_dis %>%
        dplyr::mutate(Vowel = dplyr::case_when(
          Vowel == "ae" ~ "æ",
          TRUE ~ Vowel
        ))
      
      wedge <- wedge %>%
        dplyr::mutate(Vowel = case_when(
          Vowel == "v" ~ "ʌ",
          TRUE ~ Vowel
        ))
      
      CDplot <- ggplot(aes(x=F2_b,
                           y=F1_b),
                       data = Formants_PRAAT,
                       inherit.aes = FALSE) + 
      geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) + 
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "i") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "a") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "æ") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "u") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_point(aes(x = mean_F2_b,
                     y = mean_F1_b,
                     color = Vowel),
                 data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  rbind(.,wedge),
                 inherit.aes = FALSE,
                 size = 5) +
      scale_y_reverse() +
      scale_x_reverse() +
      theme_classic() + labs(title = paste("Corner Dispersion")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1) +
          scale_color_manual(values = c("a" = "#1AAD77",
                                        "æ" = "#1279B5",
                                        "i" = "#FFBF00",
                                        "u" = "#FD7853",
                                        "ʌ" = "#BF3178"))
    CDplot
    
      rm(corner_dis, wedge)
      
## Vowel Space Area ----
  VSA_coords <- vowelData %>%
    dplyr::filter(Vowel != "v") %>%
    dplyr::group_by(Vowel) %>%
    dplyr::summarize(mean_F1 = mean(F1_tempMid),
              mean_F2 = mean(F2_tempMid),
              mean_F1_z = mean(F1_z_tempMid),
              mean_F2_z = mean(F2_z_tempMid),
              mean_F1_b = mean(F1_b_tempMid),
              mean_F2_b = mean(F2_b_tempMid)) 
  
### Plotting VSA
    VSA_coords <- VSA_coords %>%
        dplyr::mutate(Vowel = case_when(
          Vowel == "ae" ~ "æ",
          TRUE ~ Vowel
        ))
    
    VSAplot <- ggplot(aes(x = F2_b,
                          y = F1_b),
                      data = Formants_PRAAT,
                      inherit.aes = FALSE) + 
      geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) + 
      geom_polygon(aes(x = mean_F2_b,
                       y = mean_F1_b),
                   data = VSA_coords,
                   alpha = lineAlpha,
                   color = lineColor,
                   fill=NA,
                   size = 1.5) +
      geom_point(aes(x = mean_F2_b,
                     y = mean_F1_b,
                     color = Vowel),
                 data = VSA_coords,
                 inherit.aes = FALSE,
                 size = 5) +
      scale_y_reverse() +
      scale_x_reverse() +
      guides(color = FALSE) +
      theme_classic() + labs(title = "VSA") + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1) +
                scale_color_manual(values = c("a" = "#1AAD77",
                                        "æ" = "#1279B5",
                                        "i" = "#FFBF00",
                                        "u" = "#FD7853"))
    VSAplot
  
  rm(VSA_coords)
  
## Hull ----

### Plotting Hull
      convexCoords <- Formants_PRAAT %>%
        dplyr::select(F1_b, F2_b) %>%
        as.matrix() %>%
        grDevices::chull()
      convex <- Formants_PRAAT %>%
        slice(convexCoords)

      hullPlot <- ggplot(aes(F2_b, F1_b),
                         data = Formants_PRAAT) +
        geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) +
        geom_polygon(data = convex,
                     alpha = .5,
                     color = "#1279B5",
                     fill = NA,
                     size = 1.5) +
        scale_y_reverse() +
        scale_x_reverse() +
        theme_classic() + labs(title = "VSA Hull") + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1)
      hullPlot
    
  
## Vowel Space Density ----

## Bark Normalized Density ----
# selecting the bandwidth
H_hpi <- ks::Hpi(x = Formants_PRAAT[,c("F2_b","F1_b")], pilot = "samse", pre = "scale", binned = T)

# compute 2d kde
k <- kde(x = Formants_PRAAT[,c("F2_b","F1_b")],
         H = H_hpi,
         binned = T,
         gridsize = 250)

#density <- k[["estimate"]]

# Before we can plot the density estimate we need to melt it into long format
mat.melted <- data.table::melt(k$estimate)
names(mat.melted) <- c("x", "y", "density")

# We need to add two more colums to preserve the axes units
mat.melted$F2.b <- rep(k$eval.points[[1]], times = nrow(k$estimate))
mat.melted$F1.b <- rep(k$eval.points[[2]], each = nrow(k$estimate))
mat.melted$density <- scales::rescale(mat.melted$density, to = c(0, 1))

# VSD - 25
nVSD_25 <- mat.melted %>%
  dplyr::filter(density > .25) %>%
  dplyr::select(F2.b,F1.b, density) %>%
  dplyr::rename(Density = density)

convexCoords <- nVSD_25 %>%
  dplyr::select(F2.b, F1.b) %>%
  as.matrix() %>%
  #grDevices::xy.coords() %>%
  grDevices::chull()
nconvex_25 <- nVSD_25 %>%
  slice(convexCoords)

# VSD - 75
nVSD_75 <- mat.melted %>%
  dplyr::filter(density > .75) %>%
  dplyr::select(F2.b,F1.b, density) %>%
  dplyr::rename(Density = density)

convexCoords <- nVSD_75 %>%
  dplyr::select(F2.b, F1.b) %>%
  as.matrix() %>%
  grDevices::chull()
nconvex_75 <- nVSD_75 %>%
  slice(convexCoords)

# Plotting Z Normalized VSD 
    rf <- colorRampPalette(rev(RColorBrewer::brewer.pal(11, "Spectral")))
    r <- rf(32)
    
    plotData <- mat.melted %>%
                        dplyr::rename(Density = density) %>%
                        dplyr::mutate(VSDlabel = dplyr::case_when(
                          Density < .25 ~ "none",
                          Density > .25 && Density < .75 ~ "VSD25",
                          TRUE ~ "VSD75"
                        ))

    VSDplot <- ggplot(data = plotData,
                      aes(x = F2.b,
                          y = F1.b,
                          fill = Density)) + 
      geom_tile() + 
      scale_fill_viridis_c() +
      #scale_fill_gradientn(colours = r) +
      scale_x_reverse(expand = c(0, 0), 
                      breaks = round(seq(min(mat.melted$F2.b), 
                                         max(mat.melted$F2.b)))) +
      scale_y_reverse(expand = c(0, 0),
                      breaks = round(seq(min(mat.melted$F1.b),
                                         max(mat.melted$F1.b)))) + 
      ylab("F1 (bark)") + xlab("F2 (bark)") +
      labs(title = "VSD Hull") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1) +
      geom_polygon(data = nconvex_25, alpha = lineAlpha, color = lineColor, size = 1.5, fill = NA) +
      geom_polygon(data = nconvex_75, alpha = lineAlpha, color = lineColor, size = 1.5, fill = NA) +
      geom_textcurve(data = data.frame(x = 10.382452, xend = 8.313515, y = 2.874967, yend = 4.127919, Density = 1), 
                 aes(x, y, xend = xend, yend = yend),
                 hjust = 0.5,
                 vjust = -.6,
                 curvature = 0,
                 label = "VSD 25",
                 text_only = T,
                 color = "white",
                 rich = TRUE) +
        geom_textcurve(data = data.frame(x = 14.92512, xend = 12.04660, y = 3.778258, yend = 5.759672, Density = 1), 
                 aes(x, y, xend = xend, yend = yend),
                 hjust = 0.3, 
                 vjust = -.6,
                 curvature = 0,
                 label = "VSD 75",
                 text_only = T,
                 color = "white")
     VSDplot

# Combined Plot

measuresPlot <- VSAplot + CDplot + hullPlot + VSDplot +
      patchwork::plot_layout(guides = 'collect',
                             ncol = 2)

ggsave(filename = "Plots/Measures.png",
       plot = measuresPlot,
       height = 7,
       width = 8,
       scale = .8)

Filtering Process

formantAlpha <- .20
myPal <- c("#1279B5","#2D2D37")

Pitch_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = ".Pitch", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = F) %>%
    dplyr::rename(Pitch = V1) %>%
    dplyr::mutate(Pitch = gsub("--undefined--",NA,Pitch),
                  Pitch = as.numeric(Pitch))

Formants_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = "_Formant", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = T) %>%
    dplyr::select(!c(nformants, B1.Hz., B2.Hz., B3.Hz., F4.Hz., B4.Hz., F5.Hz., B5.Hz.)) %>%
    dplyr::rename(Time_s = time.s.,
                  F1_Hz = F1.Hz.,
                  F2_Hz = F2.Hz.,
                  F3_Hz = F3.Hz.) %>%
    dplyr::mutate(F1_Hz = ifelse(F1_Hz == 0, NA, F1_Hz),
                  F2_Hz = ifelse(F2_Hz == 0, NA, F2_Hz),
                  F3_Hz = ifelse(F3_Hz == 0, NA, F3_Hz)) %>%
    dplyr::mutate(F1_Hz = as.numeric(F1_Hz),
                  F2_Hz = as.numeric(F2_Hz),
                  F3_Hz = suppressWarnings(as.numeric(F3_Hz)),
                  Time_ms = Time_s / 1000,
                  F1_kHz = F1_Hz / 1000,
                  F2_kHz = F2_Hz / 1000,
                  F3_kHz = F3_Hz / 1000,
                  F1_b = emuR::bark(F1_Hz),
                  F2_b = emuR::bark(F2_Hz),
                  F3_b = emuR::bark(F3_Hz)) %>%
    dplyr::select(!Time_s) %>%
    dplyr::relocate(Time_ms, .before = F1_Hz) %>%
    cbind(.,Pitch_PRAAT)
  
  c <- 2
  while(c < NROW(Formants_PRAAT)){
    Formants_PRAAT$F1_Hz[c] <- ifelse(is.na(Formants_PRAAT$F1_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F1_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F1_Hz[c])
    Formants_PRAAT$F2_Hz[c] <- ifelse(is.na(Formants_PRAAT$F2_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F2_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F2_Hz[c])
    c <- c + 1
  }
  rm(c)
  
  # Raw Formants ----
  f1 <- ggplot(aes(x=F2_b,
                   y=F1_b),
               data = Formants_PRAAT) + 
      geom_point(shape = 21, color = myPal[2]) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() + labs(title = paste("Raw Formant Values")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Step #1: Voiced Segments ----
    plotData <- Formants_PRAAT %>%
                   dplyr::mutate(isOutlier = case_when(
                     is.na(Pitch) ~ "Removed",
                     TRUE ~ "Retained"
                   ))
    f2 <- ggplot(data = plotData,
                 aes(x = F2_b,
                     y = F1_b,
                     color = isOutlier)) + 
      geom_point(shape = 21, data = plotData %>%
                   dplyr::filter(isOutlier == "Removed")) +
      geom_point(shape = 21, data = plotData %>%
             dplyr::filter(isOutlier == "Retained")) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() + labs(title = paste("Step #1:\nVoiced Segments")) +
      xlab("F2 (bark)") +
      ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Step 2: MAD ----
    plotData <- Formants_PRAAT %>%
      dplyr::filter(!is.na(Pitch)) %>%
      dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                    F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5,
                    isOutlier = case_when(
                      F1_mad == TRUE | F2_mad == TRUE ~ "Removed",
                      TRUE ~ "Retained"
               ))
    
    f3 <- ggplot(data = plotData,
                 aes(x = F2_b,
                     y = F1_b,
                     color = isOutlier)) + 
      geom_point(shape = 21, data = plotData %>%
                   dplyr::filter(isOutlier == "Removed")) +
      geom_point(shape = 21, data = plotData %>%
             dplyr::filter(isOutlier == "Retained")) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() +
      labs(title = paste("Step #2:\nMedian Absolute Deviation")) +
      xlab("F2 (bark)") +
      ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Step 3: Mahalanhobis Distance ----
  plotData <- Formants_PRAAT %>%
      dplyr::filter(!is.na(Pitch)) %>%
      dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                    F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
      dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
      dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T)),
                  isOutlier = case_when(
                    mDist_sd < 2 ~ "Retained",
                    TRUE ~ "Removed"
                  ))
    
    f4 <- ggplot(data = plotData,
                 aes(x = F2_b,
                     y = F1_b,
                     color = isOutlier)) + 
      geom_point(shape = 21, data = plotData %>%
                   dplyr::filter(isOutlier == "Removed")) +
      geom_point(shape = 21, data = plotData %>%
             dplyr::filter(isOutlier == "Retained")) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() + labs(title = paste("Step #3:\nMahalanobis Distance")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Final Formants ----
    plotData <- Formants_PRAAT %>%
    dplyr::filter(!is.na(Pitch)) %>%
    dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                  F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
    dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
    dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T))) %>%
    dplyr::filter(mDist_sd < 2)
    
    f5 <- ggplot(aes(x=F2_b,
                     y=F1_b),
                       data = plotData,
                       inherit.aes = FALSE) + 
      geom_point(shape = 21, color = myPal[2]) + 
      scale_y_reverse() +
      scale_x_reverse() +
      theme_classic() + labs(title = paste("Final Formant Values")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1, legend.title = element_blank())
    
# Comibing plots
    filteredPlot <- f1 + f2 + f3 + f4 + f5 + patchwork::guide_area() +
      patchwork::plot_layout(guides = 'collect',
                         ncol = 3)
    filteredPlot
    
    ggsave(plot = filteredPlot, "Plots/Filtered Formants.png",
           height = 6,
           width = 8,
           units = "in",
           scale = .9)
  

OT vs. VAS

plotData_Int <- AcousticData %>%
  dplyr::filter(!grepl("_rel", Speaker)) %>%
  dplyr::group_by(Speaker) %>%
  dplyr::mutate(segMin = base::min(VAS, transAcc),
                segMax = base::max(VAS, transAcc),
                ratingAvg = mean(VAS, transAcc, na.rm = T),
                Speaker = as.factor(Speaker),
                Etiology = as.factor(Etiology)) %>%
  arrange(segMax)

my_pal <- c("#f26430", "#272D2D","#256eff")
# With a bit more style
plot_Int <- ggplot(plotData_Int) +
  geom_segment(aes(x = fct_inorder(Speaker),
                   xend = Speaker,
                   y = segMin,
                   yend = segMax,
                   color = Etiology)) +
  geom_point(aes(x = Speaker,
                 y = VAS,
                 color = Etiology),
             #color = my_pal[1],
             size = 3,
             shape = 19) +
  geom_point(aes(x = Speaker,
                 y = transAcc,
                 color = Etiology),
             #color = my_pal[2],
             size = 3,
             shape = 15) +
  coord_flip()+
  theme_classic() +
  theme(
    legend.position = "none",
    panel.border = element_blank(),
  ) +
  xlab("") +
  ylab("Speech Intelligibility") +
  ggtitle("Speech Intelligibility") +
  ylim(c(0,100))
plot_Int

myPal <- c("#1AAD77", "#1279B5", "#FFBF00", "#FD7853", "#BF3178")
myShapes <- c(16, 18, 17, 15)

scatter1 <- ggplot(plotData_Int,
                  aes(x = VAS,
                      y = transAcc,
                      color = Etiology,
                      shape = Etiology,
                      linetype = Etiology)) +
  geom_point() +
  #geom_smooth(method = "lm", se = F) +
  geom_abline(intercept = 0, slope = 1) +
  coord_cartesian(xlim = c(0,100), ylim = c(0,100)) +
  labs(x = "Intelligibility (VAS)", y = "Intelligibility (OT)") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myShapes) +
  theme_classic() +
  theme(aspect.ratio=1,
        legend.position="right")

scatter2 <- ggplot(plotData_Int,
                  aes(x = VAS,
                      y = transAcc,
                      color = Etiology,
                      shape = Etiology,
                      linetype = Etiology)) +
  #geom_point() +
  geom_smooth(method = "lm", se = F) +
  geom_abline(intercept = 0, slope = 1) +
  coord_cartesian(xlim = c(0,100), ylim = c(0,100)) +
  labs(x = "Intelligibility (VAS)", y = "Intelligibility (OT)") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myShapes) +
  theme_classic() +
  theme(aspect.ratio=1,
        legend.position="right")

combinedScatter <- ggarrange(scatter1,
                             scatter2,
                             common.legend = F,
                             ncol = 2,
                             nrow = 1)
combinedScatter

ggsave(filename = "Plots/OT and VAS Scatterplot.png",
       plot = combinedScatter,
       height = 2,
       width = 6,
       units = "in",
       scale = 1)

rm(scatter1, scatter2, combinedScatter)

Model Scatterplot

modelFigureData <- AcousticData %>%
  dplyr::filter(!grepl("_rel",Speaker)) %>%
  dplyr::select(Speaker, Etiology, Sex, VSA_b, vowel_ED_b, Hull_b, Hull_bVSD_25, Hull_bVSD_75, VAS, transAcc) %>%
  dplyr::mutate(Speaker = as.factor(Speaker),
                Etiology = as.factor(Etiology),
                Sex = as.factor(Sex)) %>%
  tidyr::pivot_longer(cols = VAS:transAcc, names_to = "IntType", values_to = "Int") %>%
  dplyr::mutate(IntType = case_when(
    IntType == "transAcc" ~ "OT",
    TRUE ~ "VAS"
  ),
                IntType = as.factor(IntType))

ylabel <- "Intelligibility"
myPal <- c("#2D2D37", "#1279B5")
myPalShape <- c(19, 1)

VSA <- modelFigureData %>%
  ggplot() +
  aes(x = VSA_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSA (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        aspect.ratio=1) +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

disp <- modelFigureData %>%
  ggplot() +
  aes(x = vowel_ED_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab("Corner Dispersion (Bark)") +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

Hull <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSA"[Hull]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

vsd25 <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_bVSD_25,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSD"[25]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

vsd75 <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_bVSD_75,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSD"[75]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

# Creating OT Scatterplot Figure

scatter <- VSA + disp + patchwork::guide_area() + Hull + vsd25 + vsd75 +
  patchwork::plot_layout(guides = 'collect',
                         ncol = 3)
scatter 

ggsave("Plots/ModelFigure.png", scatter,
       height = 4,
       width = 6,
       units = "in",
       scale = 1.1)

Listener Demographic Information


ListenerDemo <- Listeners %>%
  furniture::table1(age, gender, race, ethnicity)

ListenerDemo

Speaker Demographics


SpeakerDemo <- AcousticData %>%
  dplyr::select(c(Speaker, Sex, Etiology))

Ages <- rio::import("Prepped Data/Speaker Ages.xlsx")

SpeakerDemo <- full_join(SpeakerDemo, Ages, by = "Speaker")

SpeakerDemoInfo <- SpeakerDemo %>%
  furniture::table1(Sex, Etiology, Age, na.rm = F)

SpeakerDemoInfo

SpeakerDemo %>%
  dplyr::summarize(mean_age = mean(Age, na.rm = T), age_sd = sd(Age, na.rm = T), age_range = range(Age, na.rm = T))
LS0tCnRpdGxlOiAiVm93ZWwgQWNvdXN0aWNzIGFzIFByZWRpY3RvcnMgb2YgU3BlZWNoIEludGVsbGlnaWJpbGl0eSBpbiBEeXNhcnRocmlhIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIGlzIHRoZSBjb2RlIGZvciB0aGUgc3RhdGlzdGljYWwgYW5hbHlzaXMgZm9yICJWb3dlbCBBY291c3RpY3MgYXMgUHJlZGljdG9ycyBvZiBTcGVlY2ggSW50ZWxsaWdpYmlsaXR5IGluIER5c2FydGhyaWEuIgoKIyBMb2FkaW5nIFBhY2thZ2VzCgpgYGB7cn0KCmxpYnJhcnkocmlvKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShpcnIpICMgaW5zdGFsbC5wYWNrYWdlcygnaXJyJykKbGlicmFyeShwZXJmb3JtYW5jZSkKbGlicmFyeShjYXIpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KCJIbWlzYyIpICMgaW5zdGFsbC5wYWNrYWdlcygnSG1pc2MnKQpsaWJyYXJ5KGdncmlkZ2VzKQpsaWJyYXJ5KGZ1cm5pdHVyZSkgIyBpbnN0YWxsLnBhY2thZ2VzKCdmdXJuaXR1cmUnKQpsaWJyYXJ5KGd0KQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShrcykKbGlicmFyeShlbXVSKSAjIGluc3RhbGwucGFja2FnZXMoJ2VtdVInKQpsaWJyYXJ5KGdlb210ZXh0cGF0aCkgIyByZW1vdGVzOjppbnN0YWxsX2dpdGh1YigiQWxsYW5DYW1lcm9uL2dlb210ZXh0cGF0aCIpCgpgYGAKCiMgVXBsb2FkIERhdGFzZXRzCgpgYGB7cn0KClJlbGlhYmlsaXR5IDwtIHJpbzo6aW1wb3J0KCJQcmVwcGVkIERhdGEvUmVsaWFiaWxpdHkgRGF0YS5jc3YiKQpBY291c3RpY0RhdGEgPC0gcmlvOjppbXBvcnQoIlByZXBwZWQgRGF0YS9BY291c3RpY01lYXN1cmVzLmNzdiIpICU+JQogIGRwbHlyOjptdXRhdGUoaW50RGlmZiA9IFZBUyAtIHRyYW5zQWNjKQoKQWNvdXN0aWNEYXRhIDwtIEFjb3VzdGljRGF0YSAlPiUKICBkcGx5cjo6ZmlsdGVyKCFncmVwbCgiX3JlbCIsIFNwZWFrZXIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KGMoU3BlYWtlciwgU2V4LCBFdGlvbG9neSwgdm93ZWxfRURfYiwgVlNBX2IsIEh1bGxfYiwgSHVsbF9iVlNEXzI1LCBIdWxsX2JWU0RfNTAsIEh1bGxfYlZTRF83NSwgVkFTLCB0cmFuc0FjYykpICU+JQogIGRwbHlyOjptdXRhdGUoRXRpb2xvZ3kgPSBhcy5mYWN0b3IoRXRpb2xvZ3kpLAogICAgICAgICAgICAgICAgU2V4ID0gYXMuZmFjdG9yKFNleCksCiAgICAgICAgICAgICAgICBTcGVha2VyID0gYXMuZmFjdG9yKFNwZWFrZXIpKQoKTGlzdGVuZXJzIDwtIHJpbzo6aW1wb3J0KCJQcmVwcGVkIERhdGEvTGlzdGVuZXJfRGVtb2dyYXBoaWNzLmNzdiIpICU+JQogIGRwbHlyOjpzZWxlY3QoIWMoU3RhcnREYXRlOnByb2xvZmljSUQsIFEyLjRfNl9URVhULCBRMy4yXzhfVEVYVCwgQXVkaW9DaGVjazpFUDMpKQoKTGlzdGVuZXJzJHJhY2VbTGlzdGVuZXJzJFEzLjNfN19URVhUID09ICJOYXRpdmUgQW1lcmljYW4vIEFmcmljYW4gYW1lcmNpbmciXSA8LSAiQmlyYWNpYWwgb3IgTXVsdGlyYWNpYWwiCmBgYAoKCiMgSW50ZXItcmF0ZXIgUmVsaWFiaWxpdHkKClR3byByYXRlcnMgKHRoZSBmaXJzdCB0d28gYXV0aG9ycykgY29tcGxldGVkIHZvd2VsIHNlZ21lbnRhdGlvbiBmb3IgdGhlIHNwZWFrZXJzLiBUbyBjYWxjdWxhdGUgaW50ZXItcmF0ZXIgcmVsaWFiaWxpdHksIDIwJSBvZiB0aGUgc3BlYWtlcnMgd2VyZSBzZWdtZW50ZWQgYWdhaW4gYnkgdGhlIG90aGVyIHJhdGVyLiBUd28td2F5IGludHJhY2xhc3MgY29lZmZpY2llbnRzIHdlcmUgY29tcHV0ZWQgZm9yIHRoZSBleHRyYWN0ZWQgRjEgYW5kIEYyIGZyb20gdGhlIHRlbXBvcmFsIG1pZHBvaW50IG9mIHRoZSB2b3dlbCBzZWdtZW50cy4gU2luY2Ugb25seSBvbmUgc2V0IG9mIHJhdGluZ3Mgd2lsbCBiZSB1c2VkIGluIHRoZSBkYXRhIGFuYWx5c2lzLCB3ZSBmb2N1cyBvbiB0aGUgc2luZ2xlIElDQyByZXN1bHRzIGFuZCBpbnRlcnByZXRhdGlvbi4gSG93ZXZlciwgd2UgYWxzbyByZXBvcnQgdGhlIGF2ZXJhZ2UgSUNDIHZhbHVlcyB0byBiZSBjb21wcmVoZW5zaXZlLgoKYGBge3J9CgojIyBDcmVhdGluZyBuZXcgZGF0YSBmcmFtZXMgdG8gY2FsY3VsYXRlIElDQyBmb3IgZXh0cmFjdGVkIEYxIGFuZCBGMiB2YWx1ZXMKCkYxX1JlbCA8LSBSZWxpYWJpbGl0eSAlPiUKICBkcGx5cjo6c2VsZWN0KGMoRjEsIEYxX3JlbCkpCgpGMl9SZWwgPC0gUmVsaWFiaWxpdHkgJT4lCiAgZHBseXI6OnNlbGVjdChjKEYyLCBGMl9yZWwpKQogIAojIyBTaW5nbGUgSUNDIGZvciBGMQpTaW5nbGVfRjEgPC0gaXJyOjppY2MoRjFfUmVsLCBtb2RlbCA9ICJ0d293YXkiLCB0eXBlID0gImFncmVlbWVudCIsIHVuaXQgPSAic2luZ2xlIikKCiMjIEF2ZXJhZ2UgSUNDIGZvciBGMQpBdmVyYWdlX0YxIDwtIGlycjo6aWNjKEYxX1JlbCwgbW9kZWwgPSAidHdvd2F5IiwgdHlwZSA9ICJhZ3JlZW1lbnQiLCB1bml0ID0gImF2ZXJhZ2UiKQoKIyMgU2luZ2xlIElDQyBmb3IgRjIKU2luZ2xlX0YyIDwtIGlycjo6aWNjKEYyX1JlbCwgbW9kZWwgPSAidHdvd2F5IiwgdHlwZSA9ICJhZ3JlZW1lbnQiLCB1bml0ID0gInNpbmdsZSIpCgojIyBBdmVyYWdlIElDQyBmb3IgRjIKQXZlcmFnZV9GMiA8LSBpcnI6OmljYyhGMl9SZWwsIG1vZGVsID0gInR3b3dheSIsIHR5cGUgPSAiYWdyZWVtZW50IiwgdW5pdCA9ICJhdmVyYWdlIikKCiMjIEludGVyLXJhdGVyIHJlbGlhYmlsaXR5IHJlc3VsdHMgYW5kIGludGVycHJldGF0aW9uCgpwcmludChwYXN0ZSgiU2luZ2xlIElDQyBmb3IgRjEgaXMgIiwgcm91bmQoU2luZ2xlX0YxJHZhbHVlLCBkaWdpdHMgPSAzKSwgIi4gIiwgCiAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLCByb3VuZChTaW5nbGVfRjEkbGJvdW5kLCBkaWdpdHMgPSAzKSwgIiAtICIsIHJvdW5kKFNpbmdsZV9GMSR1Ym91bmQsIGRpZ2l0cyA9IDMpLCAiXS4iLCBzZXAgPSAiIikpCgpwcmludChwYXN0ZSgiU2luZ2xlIElDQyBmb3IgRjIgaXMgIiwgcm91bmQoU2luZ2xlX0YyJHZhbHVlLCBkaWdpdHMgPSAzKSwgIi4gIiwgCiAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLCByb3VuZChTaW5nbGVfRjIkbGJvdW5kLCBkaWdpdHMgPSAzKSwgIiAtICIsIHJvdW5kKFNpbmdsZV9GMiR1Ym91bmQsIGRpZ2l0cyA9IDMpLCAiXS4iLCBzZXAgPSAiIikpCgpwcmludChwYXN0ZSgiQXZlcmFnZSBJQ0MgZm9yIEYxIGlzICIsIHJvdW5kKEF2ZXJhZ2VfRjEkdmFsdWUsIGRpZ2l0cyA9IDMpLCAiLiAiLCAKICAgICAgICAgICAgIlRoZSA5NSUgQ0kgaXMgWyIsIHJvdW5kKEF2ZXJhZ2VfRjEkbGJvdW5kLCBkaWdpdHMgPSAzKSwgIiAtICIsIHJvdW5kKEF2ZXJhZ2VfRjEkdWJvdW5kLCBkaWdpdHMgPSAzKSwgIl0uIiwgc2VwID0gIiIpKQoKcHJpbnQocGFzdGUoIkF2ZXJhZ2UgSUNDIGZvciBGMiBpcyAiLCByb3VuZChBdmVyYWdlX0YyJHZhbHVlLCBkaWdpdHMgPSAzKSwgIi4gIiwgCiAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLCByb3VuZChBdmVyYWdlX0YyJGxib3VuZCwgZGlnaXRzID0gMyksICIgLSAiLCByb3VuZChBdmVyYWdlX0YyJHVib3VuZCwgZGlnaXRzID0gMyksICJdLiIsIHNlcCA9ICIiKSkKCnByaW50KCJUaHVzLCBpbnRlcnJhdGVyIHJlbGlhYmlsaXR5IGZvciB0aGUgZXh0cmFjdGVkIEYxIGFuZCBGMiB2YWx1ZXMgZnJvbSB0aGUgdm93ZWwgc2VnbWVudHMgd2FzIGdvb2QgdG8gZXhjZWxsZW50LiIpCgojIyBSZW1vdmluZyBleHRyYSBkYXRhIGZyYW1lcyBmcm9tIGVudmlyb25tZW50CgpybShGMV9SZWwsIEYyX1JlbCwgUmVsaWFiaWxpdHksIFNpbmdsZV9GMSwgU2luZ2xlX0YyLCBBdmVyYWdlX0YxLCBBdmVyYWdlX0YyKQoKYGBgCgoKIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzCgojIyBDb3JyZWxhdGlvbnMKCmBgYHtyfQpDb3JyTWF0cml4IDwtIEFjb3VzdGljRGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KFZTQV9iLCB2b3dlbF9FRF9iLCBIdWxsX2IsIEh1bGxfYlZTRF8yNSwgSHVsbF9iVlNEXzUwLCBIdWxsX2JWU0RfNzUsIFZBUywgdHJhbnNBY2MpICU+JQogIGFzLm1hdHJpeCgpICU+JQogIEhtaXNjOjpyY29ycigpCgpDb3JyTWF0cml4IDwtIENvcnJNYXRyaXgkcgoKc3RhdHM6OmNvci50ZXN0KEFjb3VzdGljRGF0YSRWU0FfYiwgQWNvdXN0aWNEYXRhJHZvd2VsX0VEX2IsIG1ldGhvZCA9ICJwZWFyc29uIikKc3RhdHM6OmNvci50ZXN0KEFjb3VzdGljRGF0YSRIdWxsX2IsIEFjb3VzdGljRGF0YSRIdWxsX2JWU0RfMjUsIG1ldGhvZCA9ICJwZWFyc29uIikKCndyaXRlLmNzdihDb3JyTWF0cml4LCBmaWxlID0gIlRhYmxlcy9Db3JyZWxhdGlvbiBNYXRyaXguY3N2IikKcm0oQ29yck1hdHJpeCkKCmBgYAoKIyBSZXNlYXJjaCBRMTogTW9kZWxpbmcgSW50ZWxsaWdpYmlsaXR5CgojIyBPcnRob2dyYXBoaWMgVHJhbnNjcmlwdGlvbnMKTW9kZWwgMQpgYGB7cn0KCiMgU3BlY2lmeWluZyBNb2RlbCAxCgpPVF9Nb2RlbDEgPC0gbG0odHJhbnNBY2MgfiBIdWxsX2JWU0RfMjUsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCAxIEFzc3VtcHRpb25zIAoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKE9UX01vZGVsMSkKCiMjIE1vZGVsIDEgU3VtbWFyeQoKc3VtbWFyeShPVF9Nb2RlbDEpCgpgYGAKCk1vZGVsIDIKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDIKCk9UX01vZGVsMiA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF8yNSArIEh1bGxfYlZTRF83NSwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDIgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKE9UX01vZGVsMikKCiMjIE1vZGVsIDIgU3VtbWFyeQoKc3VtbWFyeShPVF9Nb2RlbDIpCgojIyBNb2RlbCAxIGFuZCBNb2RlbCAyIENvbXBhcmlzb24KCmFub3ZhKE9UX01vZGVsMSwgT1RfTW9kZWwyKQoKYGBgCgpNb2RlbCAzCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAzCgpPVF9Nb2RlbDMgPC0gbG0odHJhbnNBY2MgfiBIdWxsX2JWU0RfMjUgKyBIdWxsX2JWU0RfNzUgKyBIdWxsX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCAzIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbDMpCgojIyBNb2RlbCAzIFN1bW1hcnkKCnN1bW1hcnkoT1RfTW9kZWwzKQoKIyMgTW9kZWwgMiBhbmQgTW9kZWwgMyBDb21wYXJpc29uCgphbm92YShPVF9Nb2RlbDIsIE9UX01vZGVsMykKCmBgYAoKTW9kZWwgNApgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgNAoKT1RfTW9kZWw0IDwtIGxtKHRyYW5zQWNjIH4gSHVsbF9iVlNEXzI1ICsgSHVsbF9iVlNEXzc1ICsgSHVsbF9iICsgVlNBX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCA0IEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbDQpCgojIyBNb2RlbCA0IFN1bW1hcnkKCnN1bW1hcnkoT1RfTW9kZWw0KQoKIyMgTW9kZWwgMyBhbmQgTW9kZWwgNCBDb21wYXJpc29uCgphbm92YShPVF9Nb2RlbDMsIE9UX01vZGVsNCkKCmBgYApNb2RlbCA1CmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCA1CgpPVF9Nb2RlbDUgPC0gbG0odHJhbnNBY2MgfiBIdWxsX2JWU0RfMjUgKyBIdWxsX2JWU0RfNzUgKyBIdWxsX2IgKyBWU0FfYiArIHZvd2VsX0VEX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCA0IEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbDUpCgojIyBNb2RlbCA0IFN1bW1hcnkKCnN1bW1hcnkoT1RfTW9kZWw1KQoKIyMgTW9kZWwgMyBhbmQgTW9kZWwgNCBDb21wYXJpc29uCgphbm92YShPVF9Nb2RlbDQsIE9UX01vZGVsNSkKCmBgYAoKCiMjIyBGaW5hbCBNb2RlbAoKYGBge3J9CgojIyBTcGVjaWZ5aW5nIEZpbmFsIE1vZGVsCgpPVF9Nb2RlbF9maW5hbCA8LSBsbSh0cmFuc0FjYyB+IFZTQV9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgRmluYWwgTW9kZWwgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKE9UX01vZGVsX2ZpbmFsKQoKIyMgRmluYWwgTW9kZWwgU3VtbWFyeQoKc3VtbWFyeShPVF9Nb2RlbF9maW5hbCkKY29uZmludChPVF9Nb2RlbF9maW5hbCkKCmBgYAoKIyMgVkFTIE1vZGVscwoKTW9kZWwgMQpgYGB7cn0KCiMgU3BlY2lmeWluZyBNb2RlbCAxCgpWQVNfTW9kZWwxIDwtIGxtKFZBUyB+IEh1bGxfYlZTRF8yNSwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDEgQXNzdW1wdGlvbnMgCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoVkFTX01vZGVsMSkKCiMjIE1vZGVsIDEgU3VtbWFyeQoKc3VtbWFyeShWQVNfTW9kZWwxKQoKYGBgCgpNb2RlbCAyCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAyCgpWQVNfTW9kZWwyIDwtIGxtKFZBUyB+IEh1bGxfYlZTRF8yNSArIEh1bGxfYlZTRF83NSwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDIgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDIpCgojIyBNb2RlbCAyIFN1bW1hcnkKCnN1bW1hcnkoVkFTX01vZGVsMikKCiMjIE1vZGVsIDEgYW5kIE1vZGVsIDIgQ29tcGFyaXNvbgoKYW5vdmEoVkFTX01vZGVsMSwgVkFTX01vZGVsMikKCmBgYAoKTW9kZWwgMwpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgMwoKVkFTX01vZGVsMyA8LSBsbShWQVMgfiBIdWxsX2JWU0RfMjUgKyBIdWxsX2JWU0RfNzUgKyBIdWxsX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCAzIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWwzKQoKIyMgTW9kZWwgMyBTdW1tYXJ5CgpzdW1tYXJ5KFZBU19Nb2RlbDMpCgojIyBNb2RlbCAyIGFuZCBNb2RlbCAzIENvbXBhcmlzb24KCmFub3ZhKFZBU19Nb2RlbDIsIFZBU19Nb2RlbDMpCgpgYGAKCk1vZGVsIDQKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDQKClZBU19Nb2RlbDQgPC0gbG0oVkFTIH4gSHVsbF9iVlNEXzI1ICsgSHVsbF9iVlNEXzc1ICsgSHVsbF9iICsgVlNBX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCA0IEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWw0KQoKIyMgTW9kZWwgNCBTdW1tYXJ5CgpzdW1tYXJ5KFZBU19Nb2RlbDQpCgojIyBNb2RlbCAzIGFuZCBNb2RlbCA0IENvbXBhcmlzb24KCmFub3ZhKFZBU19Nb2RlbDMsIFZBU19Nb2RlbDQpCgpgYGAKCk1vZGVsIDUKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDUKClZBU19Nb2RlbDUgPC0gbG0oVkFTIH4gSHVsbF9iVlNEXzI1ICsgSHVsbF9iVlNEXzc1ICsgSHVsbF9iICsgVlNBX2IgKyB2b3dlbF9FRF9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgNSBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoVkFTX01vZGVsNSkKCiMjIE1vZGVsIDUgU3VtbWFyeQoKc3VtbWFyeShWQVNfTW9kZWw1KQoKIyMgTW9kZWwgNCBhbmQgTW9kZWwgNSBDb21wYXJpc29uCgphbm92YShWQVNfTW9kZWw0LCBWQVNfTW9kZWw1KQoKYGBgCgoKIyMjIEZpbmFsIE1vZGVsCgpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgRmluYWwgTW9kZWwKClZBU19Nb2RlbF9maW5hbCA8LSBsbShWQVMgfiBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIEZpbmFsIE1vZGVsIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWxfZmluYWwpCgojIyBGaW5hbCBNb2RlbCBTdW1tYXJ5CgpzdW1tYXJ5KFZBU19Nb2RlbF9maW5hbCkKY29uZmludChWQVNfTW9kZWxfZmluYWwpCgpgYGAKCiMgUmVzZWFyY2ggUTI6IFJlbGF0aW9uc2hpcCBiZXR3ZWVuIE9UIGFuZCBWQVMKCk1vZGVsIDEKYGBge3J9CgojIFNwZWNpZnkgTW9kZWwKCk9UX1ZBU19tb2RlbCA8LSBsbSh0cmFuc0FjYyB+IFZBUypFdGlvbG9neSArIFZBUypTZXgsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9WQVNfbW9kZWwpCgojIE1vZGVsIFJlc3VsdHMKCnN1bW1hcnkoT1RfVkFTX21vZGVsKQoKYGBgCgojIyBGaW5hbCBNb2RlbAoKYGBge3J9CgojIFNwZWNpZnkgRmluYWwgTW9kZWwKCk9UX1ZBU19maW5hbCA8LSBsbSh0cmFuc0FjYyB+IFZBUywgZGF0YSA9IEFjb3VzdGljRGF0YSkKCmNvbmZpbnQoT1RfVkFTX2ZpbmFsKQoKIyBNb2RlbCBSZXN1bHRzCgpzdW1tYXJ5KE9UX1ZBU19maW5hbCkKCmBgYAoKIyBNYW51c2NyaXB0IFRhYmxlcwojI0Rlc2NyaXB0aXZlcyBUYWJsZQpgYGB7cn0KZ3REYXRhIDwtIEFjb3VzdGljRGF0YSAlPiUKICByYmluZCguLEFjb3VzdGljRGF0YSAlPiUKICAgICAgICAgIGRwbHlyOjptdXRhdGUoRXRpb2xvZ3kgPSAiQWxsIEV0aW9sb2dpZXMiKSkgJT4lCiAgcmJpbmQoLixBY291c3RpY0RhdGEgJT4lCiAgICAgICAgICByYmluZCguLEFjb3VzdGljRGF0YSAlPiUKICAgICAgICAgIGRwbHlyOjptdXRhdGUoRXRpb2xvZ3kgPSAiQWxsIEV0aW9sb2dpZXMiKSkgJT4lCiAgICAgICAgICBkcGx5cjo6bXV0YXRlKFNleCA9ICJBbGwiKSkgJT4lCiAgZHBseXI6Om11dGF0ZShTZXggPSBhcy5mYWN0b3IoU2V4KSwKICAgICAgICAgICAgICAgIEV0aW9sb2d5ID0gYXMuZmFjdG9yKEV0aW9sb2d5KSkgJT4lCiAgZHBseXI6Omdyb3VwX2J5KFNleCwgRXRpb2xvZ3kpICU+JQogIGRwbHlyOjpzdW1tYXJpemUoVlNBX21lYW4gPSBtZWFuKFZTQV9iLCBuYS5ybSA9VCksIFZTQV9zZCA9IHNkKFZTQV9iLCBuYS5ybSA9IFQpLAogICAgICAgICAgICAgICAgICAgRGlzcF9tZWFuID0gbWVhbih2b3dlbF9FRF9iLCBuYS5ybSA9VCksIERpc3Bfc2QgPSBzZCh2b3dlbF9FRF9iLCBuYS5ybSA9VCksCiAgICAgICAgICAgICAgICAgICBIdWxsX21lYW4gPSBtZWFuKEh1bGxfYiwgbmEucm0gPVQpLCBIdWxsX3NkID0gc2QoSHVsbF9iLCBuYS5ybSA9VCksCiAgICAgICAgICAgICAgICAgICBWU0QyNV9tZWFuID0gbWVhbihIdWxsX2JWU0RfMjUsIG5hLnJtID1UKSwgVlNEMjVfc2QgPSBzZChIdWxsX2JWU0RfMjUsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIFZTRDUwX21lYW4gPSBtZWFuKEh1bGxfYlZTRF81MCwgbmEucm0gPVQpLCBWU0Q1MF9zZCA9IHNkKEh1bGxfYlZTRF81MCwgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgVlNENzVfbWVhbiA9IG1lYW4oSHVsbF9iVlNEXzc1LCBuYS5ybSA9VCksIFZTRDc1X3NkID0gc2QoSHVsbF9iVlNEXzc1LCBuYS5ybSA9VCksCiAgICAgICAgICAgICAgICAgICBWQVNfbWVhbiA9IG1lYW4oVkFTLCBuYS5ybSA9VCksIFZBU19zZCA9IHNkKFZBUywgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgT1RfbWVhbiA9IG1lYW4odHJhbnNBY2MsIG5hLnJtID1UKSwgT1Rfc2QgPSBzZCh0cmFuc0FjYywgbmEucm0gPVQpKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IFZTQV9tZWFuOk9UX3NkLCBuYW1lc190byA9ICJNZWFzdXJlIiwKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIlZhbHVlIikgJT4lCiAgZHBseXI6Om11dGF0ZShtZWFuU0QgPSBpZmVsc2UoZ3JlcGwoIl9tZWFuIixNZWFzdXJlKSwiTSIsInNkIiksCiAgICAgICAgICAgICAgICBNZWFzdXJlID0gZ3N1YigiX21lYW4iLCIiLE1lYXN1cmUpLAogICAgICAgICAgICAgICAgTWVhc3VyZSA9IGdzdWIoIl9zZCIsIiIsTWVhc3VyZSksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IHBhc3RlKEV0aW9sb2d5LG1lYW5TRCwgc2VwID0gIl8iKSwKICAgICAgICAgICAgICAgIFNleCA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgU2V4ID09ICJBbGwiIH4gIkFsbCBTcGVha2VycyIsCiAgICAgICAgICAgICAgICAgIFNleCA9PSAiTSIgfiAiTWFsZSIsCiAgICAgICAgICAgICAgICAgIFNleCA9PSAiRiIgfiAiRmVtYWxlIgogICAgICAgICAgICAgICAgKSkgJT4lCiAgZHBseXI6OnNlbGVjdCghbWVhblNEKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXRpb2xvZ3ksIHZhbHVlc19mcm9tID0gIlZhbHVlIikgJT4lCiAgZHBseXI6OmZpbHRlcihNZWFzdXJlICE9ICJWU0Q1MCIpCgpndERhdGEgJT4lCiAgZ3Q6Omd0KAogICAgcm93bmFtZV9jb2wgPSAiTWVhc3VyZSIsCiAgICBncm91cG5hbWVfY29sID0gIlNleCIsCiAgKSAlPiUKICBmbXRfbnVtYmVyKAogICAgY29sdW1ucyA9ICdBbGwgRXRpb2xvZ2llc19NJzpQRF9zZCwKICAgIGRlY2ltYWxzID0gMgogICkgJT4lCiAgdGFiX3NwYW5uZXIoCiAgICBsYWJlbCA9ICJBbGwgRXRpb2xvZ2llcyIsCiAgICBjb2x1bW5zID0gYygnQWxsIEV0aW9sb2dpZXNfTScsICdBbGwgRXRpb2xvZ2llc19zZCcpCiAgKSAlPiUKICAgIHRhYl9zcGFubmVyKAogICAgbGFiZWwgPSAiQUxTIiwKICAgIGNvbHVtbnMgPSBjKEFMU19NLCBBTFNfc2QpCiAgKSAlPiUKICB0YWJfc3Bhbm5lcigKICAgIGxhYmVsID0gIlBEIiwKICAgIGNvbHVtbnMgPSBjKFBEX00sIFBEX3NkKQogICkgJT4lCiAgdGFiX3NwYW5uZXIoCiAgICBsYWJlbCA9ICJIRCIsCiAgICBjb2x1bW5zID0gYyhIRF9NLCBIRF9zZCkKICApICU+JQogIHRhYl9zcGFubmVyKAogICAgbGFiZWwgPSAiQXRheGljIiwKICAgIGNvbHVtbnMgPSBjKEF0YXhpY19NLCBBdGF4aWNfc2QpCiAgKSAlPiUKICBjb2xzX2xhYmVsKAogICAgICdBbGwgRXRpb2xvZ2llc19NJyA9ICJNIiwKICAgICAnQWxsIEV0aW9sb2dpZXNfc2QnID0gIlNEIiwKICAgICBBTFNfTSA9ICJNIiwKICAgICBBTFNfc2QgPSAiU0QiLAogICAgIFBEX00gPSAiTSIsCiAgICAgUERfc2QgPSAiU0QiLAogICAgIEhEX00gPSAiTSIsCiAgICAgSERfc2QgPSAiU0QiLAogICAgIEF0YXhpY19NID0gIk0iLAogICAgIEF0YXhpY19zZCA9ICJTRCIKICApICU+JQogIGd0c2F2ZSgiRGVzY3JpcHRpdmVzVGFibGUuaHRtbCIsIHBhdGggPSAiVGFibGVzIikKCmBgYAoKIyMgT1QgTW9kZWwKYGBge3J9CnNqUGxvdDo6dGFiX21vZGVsKE9UX01vZGVsMSxPVF9Nb2RlbDIsT1RfTW9kZWwzLCBPVF9Nb2RlbDQsIE9UX01vZGVsNSwgT1RfTW9kZWxfZmluYWwsCiAgICAgICAgICAgICAgICAgIHNob3cuY2kgPSBGLAogICAgICAgICAgICAgICAgICBwLnN0eWxlID0gInN0YXJzIiwKICAgICAgICAgICAgICAgICAgZmlsZSA9ICJUYWJsZXMvT1QgTW9kZWxzLmh0bWwiKQpgYGAKCiMjIFZBUyBNb2RlbApgYGB7cn0Kc2pQbG90Ojp0YWJfbW9kZWwoVkFTX01vZGVsMSxWQVNfTW9kZWwyLFZBU19Nb2RlbDMsIFZBU19Nb2RlbDQsIFZBU19Nb2RlbDUsIFZBU19Nb2RlbF9maW5hbCwKICAgICAgICAgICAgICAgICAgc2hvdy5jaSA9IEYsCiAgICAgICAgICAgICAgICAgIHAuc3R5bGUgPSAic3RhcnMiLAogICAgICAgICAgICAgICAgICBmaWxlID0gIlRhYmxlcy9WQVMgTW9kZWxzLmh0bWwiKQpgYGAKCiMjIE9UIHZzLiBWQVMKYGBge3J9CnNqUGxvdDo6dGFiX21vZGVsKE9UX1ZBU19tb2RlbCxPVF9WQVNfZmluYWwsCiAgICAgICAgICAgICAgICAgIHNob3cuY2kgPSBGLAogICAgICAgICAgICAgICAgICBzaG93LnJlZmx2bCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgIHAuc3R5bGUgPSAic3RhcnMiLAogICAgICAgICAgICAgICAgICBmaWxlID0gIlRhYmxlcy9PVCBhbmQgVkFTIENvbXBhcmlzb24uaHRtbCIpCmBgYAoKIyBNYW51c2NyaXB0IEZpZ3VyZXMKIyMgRXhhbXBsZSBNZWFzdXJlcwpgYGB7cn0KZm9ybWFudENvbG9yIDwtICJncmV5Igpmb3JtYW50QWxwaGEgPC0gLjk1CmxpbmVDb2xvciA8LSAid2hpdGUiCmxpbmVBbHBoYSA8LSAuOAoKdm93ZWxEYXRhIDwtIHJpbzo6aW1wb3J0KCJQcmVwcGVkIERhdGEvVm93ZWwgRGF0YS5jc3YiKSAlPiUKICBkcGx5cjo6ZmlsdGVyKFNwZWFrZXIgPT0gIkFGOCIpCgogIFBpdGNoX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiLlBpdGNoIiwgaWdub3JlLmNhc2UgPSBUKSAlPiUKICAgIHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsLiwgc2VwID0gIiIpICU+JQogICAgcmVhZC5kZWxpbSguLCBoZWFkZXIgPSBGKSAlPiUKICAgIGRwbHlyOjpyZW5hbWUoUGl0Y2ggPSBWMSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKFBpdGNoID0gZ3N1YigiLS11bmRlZmluZWQtLSIsTkEsUGl0Y2gpLAogICAgICAgICAgICAgICAgICBQaXRjaCA9IGFzLm51bWVyaWMoUGl0Y2gpKQogIAogIEZvcm1hbnRzX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiX0Zvcm1hbnQiLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IFQpICU+JQogICAgZHBseXI6OnNlbGVjdCghYyhuZm9ybWFudHMsIEIxLkh6LiwgQjIuSHouLCBCMy5Iei4sIEY0Lkh6LiwgQjQuSHouLCBGNS5Iei4sIEI1Lkh6LikpICU+JQogICAgZHBseXI6OnJlbmFtZShUaW1lX3MgPSB0aW1lLnMuLAogICAgICAgICAgICAgICAgICBGMV9IeiA9IEYxLkh6LiwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBGMi5Iei4sCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gRjMuSHouKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBpZmVsc2UoRjFfSHogPT0gMCwgTkEsIEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBpZmVsc2UoRjJfSHogPT0gMCwgTkEsIEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBpZmVsc2UoRjNfSHogPT0gMCwgTkEsIEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gYXMubnVtZXJpYyhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gYXMubnVtZXJpYyhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKEYzX0h6KSksCiAgICAgICAgICAgICAgICAgIFRpbWVfbXMgPSBUaW1lX3MgLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9rSHogPSBGMV9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYyX2tIeiA9IEYyX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjNfa0h6ID0gRjNfSHogLyAxMDAwKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIVRpbWVfcykgJT4lCiAgICBkcGx5cjo6cmVsb2NhdGUoVGltZV9tcywgLmJlZm9yZSA9IEYxX0h6KSAlPiUKICAgIGNiaW5kKC4sUGl0Y2hfUFJBQVQpCiAgCiAgYyA8LSAyCiAgd2hpbGUoYyA8IE5ST1coRm9ybWFudHNfUFJBQVQpKXsKICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdIDwtIGlmZWxzZShpcy5uYShGb3JtYW50c19QUkFBVCRGMV9IeltjLTFdKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYysxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9ybWFudHNfUFJBQVQkRjFfSHpbY10pCiAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjJfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYyX0h6W2NdKQogICAgYyA8LSBjICsgMQogIH0KICBybShjKQogIAogIEZvcm1hbnRzX1BSQUFUIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1EaXN0X3NkIDwgMikgJT4lCiAgICBkcGx5cjo6c2VsZWN0KCFjKEYxX21hZCwgRjJfbWFkLCBtRGlzdCwgbURpc3Rfc2QpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfeiA9IHNjYWxlKEYxX0h6LCBjZW50ZXIgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgRjJfeiA9IHNjYWxlKEYyX0h6LCBjZW50ZXIgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgRjNfeiA9IHNjYWxlKEYzX0h6LCBjZW50ZXIgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgRjFfYiA9IGVtdVI6OmJhcmsoRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9iID0gZW11Ujo6YmFyayhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX2IgPSBlbXVSOjpiYXJrKEYzX0h6KSkKICAKICBybShQaXRjaF9QUkFBVCkKICAKICAKIyMgQ29ybmVyIERpc3BlcnNpb24gLS0tLQogIHdlZGdlIDwtIHZvd2VsRGF0YSAlPiUKICAgIGRwbHlyOjpncm91cF9ieShWb3dlbCkgJT4lCiAgICBkcGx5cjo6c3VtbWFyaXplKG1lYW5fRjEgPSBtZWFuKEYxX3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjIgPSBtZWFuKEYyX3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjFfeiA9IG1lYW4oRjFfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YyX3ogPSBtZWFuKEYyX3pfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV9iID0gbWVhbihGMV9iX3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfYiA9IG1lYW4oRjJfYl90ZW1wTWlkKSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKFZvd2VsID09ICJ2IikKICAgIAogIGNvcm5lcl9kaXMgPC0gdm93ZWxEYXRhICU+JQogICAgZHBseXI6OmZpbHRlcihWb3dlbCAhPSAidiIpICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFZvd2VsKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobWVhbl9GMSA9IG1lYW4oRjFfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMiA9IG1lYW4oRjJfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV96ID0gbWVhbihGMV96X3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfeiA9IG1lYW4oRjJfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YxX2IgPSBtZWFuKEYxX2JfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMl9iID0gbWVhbihGMl9iX3RlbXBNaWQpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoVm93ZWxfRUQgPSBzcXJ0KChtZWFuX0YxLXdlZGdlJG1lYW5fRjEpXjIgKyAobWVhbl9GMi13ZWRnZSRtZWFuX0YyKV4yKSwKICAgICAgICAgICAgICAgICAgVm93ZWxfRURfeiA9IHNxcnQoKG1lYW5fRjFfei13ZWRnZSRtZWFuX0YxX3opXjIgKyAobWVhbl9GMl96LXdlZGdlJG1lYW5fRjJfeileMiksCiAgICAgICAgICAgICAgICAgIFZvd2VsX0VEX2IgPSBzcXJ0KChtZWFuX0YxX2Itd2VkZ2UkbWVhbl9GMV9iKV4yICsgKG1lYW5fRjJfYi13ZWRnZSRtZWFuX0YyX2IpXjIpKQoKICAgIAojIFBsb3QgQ29ybmVyIERpc3BlcnNpb24KICAgICAgIyBDaGFuZ2luZyB0byBJUEEgc3ltYm9scwogICAgICBjb3JuZXJfZGlzIDwtIGNvcm5lcl9kaXMgJT4lCiAgICAgICAgZHBseXI6Om11dGF0ZShWb3dlbCA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICBWb3dlbCA9PSAiYWUiIH4gIsOmIiwKICAgICAgICAgIFRSVUUgfiBWb3dlbAogICAgICAgICkpCiAgICAgIAogICAgICB3ZWRnZSA8LSB3ZWRnZSAlPiUKICAgICAgICBkcGx5cjo6bXV0YXRlKFZvd2VsID0gY2FzZV93aGVuKAogICAgICAgICAgVm93ZWwgPT0gInYiIH4gIsqMIiwKICAgICAgICAgIFRSVUUgfiBWb3dlbAogICAgICAgICkpCiAgICAgIAogICAgICBDRHBsb3QgPC0gZ2dwbG90KGFlcyh4PUYyX2IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9RjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IEZvcm1hbnRzX1BSQUFULAogICAgICAgICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwKICAgICAgICAgICAgICAgICBhbHBoYSA9IGZvcm1hbnRBbHBoYSwKICAgICAgICAgICAgICAgICBjb2xvciA9IGZvcm1hbnRDb2xvcikgKyAKICAgICAgZ2VvbV9saW5lKGFlcyh4ID0gbWVhbl9GMl9iLAogICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0YxX2IpLAogICAgICAgICAgICAgICAgZGF0YSA9IGNvcm5lcl9kaXMgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoVm93ZWw6bWVhbl9GMl9iKSAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihWb3dlbCA9PSAiaSIpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgIGNvbG9yID0gbGluZUNvbG9yLAogICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwKICAgICAgICAgICAgICAgIGFscGhhID0gbGluZUFscGhhKSArCiAgICAgIGdlb21fbGluZShhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgIGRhdGEgPSBjb3JuZXJfZGlzICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KFZvd2VsOm1lYW5fRjJfYikgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoVm93ZWwgPT0gImEiKSAlPiUKICAgICAgICAgICAgICAgICAgcmJpbmQoLix3ZWRnZSksCiAgICAgICAgICAgICAgICBjb2xvciA9IGxpbmVDb2xvciwKICAgICAgICAgICAgICAgIHNpemUgPSAxLjUsCiAgICAgICAgICAgICAgICBhbHBoYSA9IGxpbmVBbHBoYSkgKwogICAgICBnZW9tX2xpbmUoYWVzKHggPSBtZWFuX0YyX2IsCiAgICAgICAgICAgICAgICAgICAgeSA9IG1lYW5fRjFfYiksCiAgICAgICAgICAgICAgICBkYXRhID0gY29ybmVyX2RpcyAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChWb3dlbDptZWFuX0YyX2IpICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKFZvd2VsID09ICLDpiIpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgIGNvbG9yID0gbGluZUNvbG9yLAogICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwKICAgICAgICAgICAgICAgIGFscGhhID0gbGluZUFscGhhKSArCiAgICAgIGdlb21fbGluZShhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgIGRhdGEgPSBjb3JuZXJfZGlzICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KFZvd2VsOm1lYW5fRjJfYikgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoVm93ZWwgPT0gInUiKSAlPiUKICAgICAgICAgICAgICAgICAgcmJpbmQoLix3ZWRnZSksCiAgICAgICAgICAgICAgICBjb2xvciA9IGxpbmVDb2xvciwKICAgICAgICAgICAgICAgIHNpemUgPSAxLjUsCiAgICAgICAgICAgICAgICBhbHBoYSA9IGxpbmVBbHBoYSkgKwogICAgICBnZW9tX3BvaW50KGFlcyh4ID0gbWVhbl9GMl9iLAogICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IFZvd2VsKSwKICAgICAgICAgICAgICAgICBkYXRhID0gY29ybmVyX2RpcyAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChWb3dlbDptZWFuX0YyX2IpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgIHNpemUgPSA1KSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIkNvcm5lciBEaXNwZXJzaW9uIikpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxKSArCiAgICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYSIgPSAiIzFBQUQ3NyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiw6YiID0gIiMxMjc5QjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImkiID0gIiNGRkJGMDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInUiID0gIiNGRDc4NTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIsqMIiA9ICIjQkYzMTc4IikpCiAgICBDRHBsb3QKICAgIAogICAgICBybShjb3JuZXJfZGlzLCB3ZWRnZSkKICAgICAgCiMjIFZvd2VsIFNwYWNlIEFyZWEgLS0tLQogIFZTQV9jb29yZHMgPC0gdm93ZWxEYXRhICU+JQogICAgZHBseXI6OmZpbHRlcihWb3dlbCAhPSAidiIpICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFZvd2VsKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobWVhbl9GMSA9IG1lYW4oRjFfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMiA9IG1lYW4oRjJfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV96ID0gbWVhbihGMV96X3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfeiA9IG1lYW4oRjJfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YxX2IgPSBtZWFuKEYxX2JfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMl9iID0gbWVhbihGMl9iX3RlbXBNaWQpKSAKICAKIyMjIFBsb3R0aW5nIFZTQQogICAgVlNBX2Nvb3JkcyA8LSBWU0FfY29vcmRzICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoVm93ZWwgPSBjYXNlX3doZW4oCiAgICAgICAgICBWb3dlbCA9PSAiYWUiIH4gIsOmIiwKICAgICAgICAgIFRSVUUgfiBWb3dlbAogICAgICAgICkpCiAgICAKICAgIFZTQXBsb3QgPC0gZ2dwbG90KGFlcyh4ID0gRjJfYiwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQsCiAgICAgICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgYWxwaGEgPSBmb3JtYW50QWxwaGEsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBmb3JtYW50Q29sb3IpICsgCiAgICAgIGdlb21fcG9seWdvbihhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgICAgIGRhdGEgPSBWU0FfY29vcmRzLAogICAgICAgICAgICAgICAgICAgYWxwaGEgPSBsaW5lQWxwaGEsCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IGxpbmVDb2xvciwKICAgICAgICAgICAgICAgICAgIGZpbGw9TkEsCiAgICAgICAgICAgICAgICAgICBzaXplID0gMS41KSArCiAgICAgIGdlb21fcG9pbnQoYWVzKHggPSBtZWFuX0YyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0YxX2IsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gVm93ZWwpLAogICAgICAgICAgICAgICAgIGRhdGEgPSBWU0FfY29vcmRzLAogICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgc2l6ZSA9IDUpICsKICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgIGd1aWRlcyhjb2xvciA9IEZBTFNFKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSAiVlNBIikgKyB4bGFiKCJGMiAoYmFyaykiKSArIHlsYWIoIkYxIChiYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpICsKICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJhIiA9ICIjMUFBRDc3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLDpiIgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiaSIgPSAiI0ZGQkYwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidSIgPSAiI0ZENzg1MyIpKQogICAgVlNBcGxvdAogIAogIHJtKFZTQV9jb29yZHMpCiAgCiMjIEh1bGwgLS0tLQoKIyMjIFBsb3R0aW5nIEh1bGwKICAgICAgY29udmV4Q29vcmRzIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoRjFfYiwgRjJfYikgJT4lCiAgICAgICAgYXMubWF0cml4KCkgJT4lCiAgICAgICAgZ3JEZXZpY2VzOjpjaHVsbCgpCiAgICAgIGNvbnZleCA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgICBzbGljZShjb252ZXhDb29yZHMpCgogICAgICBodWxsUGxvdCA8LSBnZ3Bsb3QoYWVzKEYyX2IsIEYxX2IpLAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IEZvcm1hbnRzX1BSQUFUKSArCiAgICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLAogICAgICAgICAgICAgICAgIGFscGhhID0gZm9ybWFudEFscGhhLAogICAgICAgICAgICAgICAgIGNvbG9yID0gZm9ybWFudENvbG9yKSArCiAgICAgICAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBjb252ZXgsCiAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gLjUsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMxMjc5QjUiLAogICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsKICAgICAgICBzY2FsZV95X3JldmVyc2UoKSArCiAgICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSAiVlNBIEh1bGwiKSArIHhsYWIoIkYyIChiYXJrKSIpICsgeWxhYigiRjEgKGJhcmspIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSkKICAgICAgaHVsbFBsb3QKICAgIAogIAojIyBWb3dlbCBTcGFjZSBEZW5zaXR5IC0tLS0KCiMjIEJhcmsgTm9ybWFsaXplZCBEZW5zaXR5IC0tLS0KIyBzZWxlY3RpbmcgdGhlIGJhbmR3aWR0aApIX2hwaSA8LSBrczo6SHBpKHggPSBGb3JtYW50c19QUkFBVFssYygiRjJfYiIsIkYxX2IiKV0sIHBpbG90ID0gInNhbXNlIiwgcHJlID0gInNjYWxlIiwgYmlubmVkID0gVCkKCiMgY29tcHV0ZSAyZCBrZGUKayA8LSBrZGUoeCA9IEZvcm1hbnRzX1BSQUFUWyxjKCJGMl9iIiwiRjFfYiIpXSwKICAgICAgICAgSCA9IEhfaHBpLAogICAgICAgICBiaW5uZWQgPSBULAogICAgICAgICBncmlkc2l6ZSA9IDI1MCkKCiNkZW5zaXR5IDwtIGtbWyJlc3RpbWF0ZSJdXQoKIyBCZWZvcmUgd2UgY2FuIHBsb3QgdGhlIGRlbnNpdHkgZXN0aW1hdGUgd2UgbmVlZCB0byBtZWx0IGl0IGludG8gbG9uZyBmb3JtYXQKbWF0Lm1lbHRlZCA8LSBkYXRhLnRhYmxlOjptZWx0KGskZXN0aW1hdGUpCm5hbWVzKG1hdC5tZWx0ZWQpIDwtIGMoIngiLCAieSIsICJkZW5zaXR5IikKCiMgV2UgbmVlZCB0byBhZGQgdHdvIG1vcmUgY29sdW1zIHRvIHByZXNlcnZlIHRoZSBheGVzIHVuaXRzCm1hdC5tZWx0ZWQkRjIuYiA8LSByZXAoayRldmFsLnBvaW50c1tbMV1dLCB0aW1lcyA9IG5yb3coayRlc3RpbWF0ZSkpCm1hdC5tZWx0ZWQkRjEuYiA8LSByZXAoayRldmFsLnBvaW50c1tbMl1dLCBlYWNoID0gbnJvdyhrJGVzdGltYXRlKSkKbWF0Lm1lbHRlZCRkZW5zaXR5IDwtIHNjYWxlczo6cmVzY2FsZShtYXQubWVsdGVkJGRlbnNpdHksIHRvID0gYygwLCAxKSkKCiMgVlNEIC0gMjUKblZTRF8yNSA8LSBtYXQubWVsdGVkICU+JQogIGRwbHlyOjpmaWx0ZXIoZGVuc2l0eSA+IC4yNSkgJT4lCiAgZHBseXI6OnNlbGVjdChGMi5iLEYxLmIsIGRlbnNpdHkpICU+JQogIGRwbHlyOjpyZW5hbWUoRGVuc2l0eSA9IGRlbnNpdHkpCgpjb252ZXhDb29yZHMgPC0gblZTRF8yNSAlPiUKICBkcGx5cjo6c2VsZWN0KEYyLmIsIEYxLmIpICU+JQogIGFzLm1hdHJpeCgpICU+JQogICNnckRldmljZXM6Onh5LmNvb3JkcygpICU+JQogIGdyRGV2aWNlczo6Y2h1bGwoKQpuY29udmV4XzI1IDwtIG5WU0RfMjUgJT4lCiAgc2xpY2UoY29udmV4Q29vcmRzKQoKIyBWU0QgLSA3NQpuVlNEXzc1IDwtIG1hdC5tZWx0ZWQgJT4lCiAgZHBseXI6OmZpbHRlcihkZW5zaXR5ID4gLjc1KSAlPiUKICBkcGx5cjo6c2VsZWN0KEYyLmIsRjEuYiwgZGVuc2l0eSkgJT4lCiAgZHBseXI6OnJlbmFtZShEZW5zaXR5ID0gZGVuc2l0eSkKCmNvbnZleENvb3JkcyA8LSBuVlNEXzc1ICU+JQogIGRwbHlyOjpzZWxlY3QoRjIuYiwgRjEuYikgJT4lCiAgYXMubWF0cml4KCkgJT4lCiAgZ3JEZXZpY2VzOjpjaHVsbCgpCm5jb252ZXhfNzUgPC0gblZTRF83NSAlPiUKICBzbGljZShjb252ZXhDb29yZHMpCgojIFBsb3R0aW5nIFogTm9ybWFsaXplZCBWU0QgCiAgICByZiA8LSBjb2xvclJhbXBQYWxldHRlKHJldihSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwoMTEsICJTcGVjdHJhbCIpKSkKICAgIHIgPC0gcmYoMzIpCiAgICAKICAgIHBsb3REYXRhIDwtIG1hdC5tZWx0ZWQgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgIGRwbHlyOjpyZW5hbWUoRGVuc2l0eSA9IGRlbnNpdHkpICU+JQogICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6bXV0YXRlKFZTRGxhYmVsID0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgICAgICAgICBEZW5zaXR5IDwgLjI1IH4gIm5vbmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgIERlbnNpdHkgPiAuMjUgJiYgRGVuc2l0eSA8IC43NSB+ICJWU0QyNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJWU0Q3NSIKICAgICAgICAgICAgICAgICAgICAgICAgKSkKCiAgICBWU0RwbG90IDwtIGdncGxvdChkYXRhID0gcGxvdERhdGEsCiAgICAgICAgICAgICAgICAgICAgICBhZXMoeCA9IEYyLmIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IEYxLmIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IERlbnNpdHkpKSArIAogICAgICBnZW9tX3RpbGUoKSArIAogICAgICBzY2FsZV9maWxsX3ZpcmlkaXNfYygpICsKICAgICAgI3NjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG91cnMgPSByKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZShleHBhbmQgPSBjKDAsIDApLCAKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHJvdW5kKHNlcShtaW4obWF0Lm1lbHRlZCRGMi5iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4KG1hdC5tZWx0ZWQkRjIuYikpKSkgKwogICAgICBzY2FsZV95X3JldmVyc2UoZXhwYW5kID0gYygwLCAwKSwKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHJvdW5kKHNlcShtaW4obWF0Lm1lbHRlZCRGMS5iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgobWF0Lm1lbHRlZCRGMS5iKSkpKSArIAogICAgICB5bGFiKCJGMSAoYmFyaykiKSArIHhsYWIoIkYyIChiYXJrKSIpICsKICAgICAgbGFicyh0aXRsZSA9ICJWU0QgSHVsbCIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpICsKICAgICAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBuY29udmV4XzI1LCBhbHBoYSA9IGxpbmVBbHBoYSwgY29sb3IgPSBsaW5lQ29sb3IsIHNpemUgPSAxLjUsIGZpbGwgPSBOQSkgKwogICAgICBnZW9tX3BvbHlnb24oZGF0YSA9IG5jb252ZXhfNzUsIGFscGhhID0gbGluZUFscGhhLCBjb2xvciA9IGxpbmVDb2xvciwgc2l6ZSA9IDEuNSwgZmlsbCA9IE5BKSArCiAgICAgIGdlb21fdGV4dGN1cnZlKGRhdGEgPSBkYXRhLmZyYW1lKHggPSAxMC4zODI0NTIsIHhlbmQgPSA4LjMxMzUxNSwgeSA9IDIuODc0OTY3LCB5ZW5kID0gNC4xMjc5MTksIERlbnNpdHkgPSAxKSwgCiAgICAgICAgICAgICAgICAgYWVzKHgsIHksIHhlbmQgPSB4ZW5kLCB5ZW5kID0geWVuZCksCiAgICAgICAgICAgICAgICAgaGp1c3QgPSAwLjUsCiAgICAgICAgICAgICAgICAgdmp1c3QgPSAtLjYsCiAgICAgICAgICAgICAgICAgY3VydmF0dXJlID0gMCwKICAgICAgICAgICAgICAgICBsYWJlbCA9ICJWU0QgMjUiLAogICAgICAgICAgICAgICAgIHRleHRfb25seSA9IFQsCiAgICAgICAgICAgICAgICAgY29sb3IgPSAid2hpdGUiLAogICAgICAgICAgICAgICAgIHJpY2ggPSBUUlVFKSArCiAgICAgICAgZ2VvbV90ZXh0Y3VydmUoZGF0YSA9IGRhdGEuZnJhbWUoeCA9IDE0LjkyNTEyLCB4ZW5kID0gMTIuMDQ2NjAsIHkgPSAzLjc3ODI1OCwgeWVuZCA9IDUuNzU5NjcyLCBEZW5zaXR5ID0gMSksIAogICAgICAgICAgICAgICAgIGFlcyh4LCB5LCB4ZW5kID0geGVuZCwgeWVuZCA9IHllbmQpLAogICAgICAgICAgICAgICAgIGhqdXN0ID0gMC4zLCAKICAgICAgICAgICAgICAgICB2anVzdCA9IC0uNiwKICAgICAgICAgICAgICAgICBjdXJ2YXR1cmUgPSAwLAogICAgICAgICAgICAgICAgIGxhYmVsID0gIlZTRCA3NSIsCiAgICAgICAgICAgICAgICAgdGV4dF9vbmx5ID0gVCwKICAgICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIpCiAgICAgVlNEcGxvdAoKIyBDb21iaW5lZCBQbG90CgptZWFzdXJlc1Bsb3QgPC0gVlNBcGxvdCArIENEcGxvdCArIGh1bGxQbG90ICsgVlNEcGxvdCArCiAgICAgIHBhdGNod29yazo6cGxvdF9sYXlvdXQoZ3VpZGVzID0gJ2NvbGxlY3QnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAyKQoKZ2dzYXZlKGZpbGVuYW1lID0gIlBsb3RzL01lYXN1cmVzLnBuZyIsCiAgICAgICBwbG90ID0gbWVhc3VyZXNQbG90LAogICAgICAgaGVpZ2h0ID0gNywKICAgICAgIHdpZHRoID0gOCwKICAgICAgIHNjYWxlID0gLjgpCgpgYGAKCiMjIEZpbHRlcmluZyBQcm9jZXNzCmBgYHtyfQpmb3JtYW50QWxwaGEgPC0gLjIwCm15UGFsIDwtIGMoIiMxMjc5QjUiLCIjMkQyRDM3IikKClBpdGNoX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiLlBpdGNoIiwgaWdub3JlLmNhc2UgPSBUKSAlPiUKICAgIHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsLiwgc2VwID0gIiIpICU+JQogICAgcmVhZC5kZWxpbSguLCBoZWFkZXIgPSBGKSAlPiUKICAgIGRwbHlyOjpyZW5hbWUoUGl0Y2ggPSBWMSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKFBpdGNoID0gZ3N1YigiLS11bmRlZmluZWQtLSIsTkEsUGl0Y2gpLAogICAgICAgICAgICAgICAgICBQaXRjaCA9IGFzLm51bWVyaWMoUGl0Y2gpKQoKRm9ybWFudHNfUFJBQVQgPC0gbGlzdC5maWxlcyhwYXRoID0gcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJfRm9ybWFudCIsIGlnbm9yZS5jYXNlID0gVCkgJT4lCiAgICBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS8iLC4sIHNlcCA9ICIiKSAlPiUKICAgIHJlYWQuZGVsaW0oLiwgaGVhZGVyID0gVCkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KCFjKG5mb3JtYW50cywgQjEuSHouLCBCMi5Iei4sIEIzLkh6LiwgRjQuSHouLCBCNC5Iei4sIEY1Lkh6LiwgQjUuSHouKSkgJT4lCiAgICBkcGx5cjo6cmVuYW1lKFRpbWVfcyA9IHRpbWUucy4sCiAgICAgICAgICAgICAgICAgIEYxX0h6ID0gRjEuSHouLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IEYyLkh6LiwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBGMy5Iei4pICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9IeiA9IGlmZWxzZShGMV9IeiA9PSAwLCBOQSwgRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IGlmZWxzZShGMl9IeiA9PSAwLCBOQSwgRjJfSHopLAogICAgICAgICAgICAgICAgICBGM19IeiA9IGlmZWxzZShGM19IeiA9PSAwLCBOQSwgRjNfSHopKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBhcy5udW1lcmljKEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBhcy5udW1lcmljKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMoRjNfSHopKSwKICAgICAgICAgICAgICAgICAgVGltZV9tcyA9IFRpbWVfcyAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYxX2tIeiA9IEYxX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjJfa0h6ID0gRjJfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGM19rSHogPSBGM19IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYxX2IgPSBlbXVSOjpiYXJrKEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfYiA9IGVtdVI6OmJhcmsoRjJfSHopLAogICAgICAgICAgICAgICAgICBGM19iID0gZW11Ujo6YmFyayhGM19IeikpICU+JQogICAgZHBseXI6OnNlbGVjdCghVGltZV9zKSAlPiUKICAgIGRwbHlyOjpyZWxvY2F0ZShUaW1lX21zLCAuYmVmb3JlID0gRjFfSHopICU+JQogICAgY2JpbmQoLixQaXRjaF9QUkFBVCkKICAKICBjIDwtIDIKICB3aGlsZShjIDwgTlJPVyhGb3JtYW50c19QUkFBVCkpewogICAgRm9ybWFudHNfUFJBQVQkRjFfSHpbY10gPC0gaWZlbHNlKGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYxX0h6W2MtMV0pICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShGb3JtYW50c19QUkFBVCRGMV9IeltjKzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb3JtYW50c19QUkFBVCRGMV9IeltjXSkKICAgIEZvcm1hbnRzX1BSQUFUJEYyX0h6W2NdIDwtIGlmZWxzZShpcy5uYShGb3JtYW50c19QUkFBVCRGMl9IeltjLTFdKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoRm9ybWFudHNfUFJBQVQkRjJfSHpbYysxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9ybWFudHNfUFJBQVQkRjJfSHpbY10pCiAgICBjIDwtIGMgKyAxCiAgfQogIHJtKGMpCiAgCiAgIyBSYXcgRm9ybWFudHMgLS0tLQogIGYxIDwtIGdncGxvdChhZXMoeD1GMl9iLAogICAgICAgICAgICAgICAgICAgeT1GMV9iKSwKICAgICAgICAgICAgICAgZGF0YSA9IEZvcm1hbnRzX1BSQUFUKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGNvbG9yID0gbXlQYWxbMl0pICsKICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIlJhdyBGb3JtYW50IFZhbHVlcyIpKSArIHhsYWIoIkYyIChiYXJrKSIpICsgeWxhYigiRjEgKGJhcmspIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSwKICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkKICAgIAojIFN0ZXAgIzE6IFZvaWNlZCBTZWdtZW50cyAtLS0tCiAgICBwbG90RGF0YSA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgICAgICAgICAgICAgIGRwbHlyOjptdXRhdGUoaXNPdXRsaWVyID0gY2FzZV93aGVuKAogICAgICAgICAgICAgICAgICAgICBpcy5uYShQaXRjaCkgfiAiUmVtb3ZlZCIsCiAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiUmV0YWluZWQiCiAgICAgICAgICAgICAgICAgICApKQogICAgZjIgPC0gZ2dwbG90KGRhdGEgPSBwbG90RGF0YSwKICAgICAgICAgICAgICAgICBhZXMoeCA9IEYyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBGMV9iLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGlzT3V0bGllcikpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZGF0YSA9IHBsb3REYXRhICU+JQogICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihpc091dGxpZXIgPT0gIlJlbW92ZWQiKSkgKwogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGRhdGEgPSBwbG90RGF0YSAlPiUKICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoaXNPdXRsaWVyID09ICJSZXRhaW5lZCIpKSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICAgICAgdGhlbWVfY2xhc3NpYygpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJTdGVwICMxOlxuVm9pY2VkIFNlZ21lbnRzIikpICsKICAgICAgeGxhYigiRjIgKGJhcmspIikgKwogICAgICB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxLAogICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKQogICAgCiMgU3RlcCAyOiBNQUQgLS0tLQogICAgcGxvdERhdGEgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKFBpdGNoKSkgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgICAgRjJfbWFkID0gKGFicyhGMl9IeiAtIG1lZGlhbihGMl9IeikpLyBtYWQoRjJfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgICAgaXNPdXRsaWVyID0gY2FzZV93aGVuKAogICAgICAgICAgICAgICAgICAgICAgRjFfbWFkID09IFRSVUUgfCBGMl9tYWQgPT0gVFJVRSB+ICJSZW1vdmVkIiwKICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiUmV0YWluZWQiCiAgICAgICAgICAgICAgICkpCiAgICAKICAgIGYzIDwtIGdncGxvdChkYXRhID0gcGxvdERhdGEsCiAgICAgICAgICAgICAgICAgYWVzKHggPSBGMl9iLAogICAgICAgICAgICAgICAgICAgICB5ID0gRjFfYiwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBpc091dGxpZXIpKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGRhdGEgPSBwbG90RGF0YSAlPiUKICAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoaXNPdXRsaWVyID09ICJSZW1vdmVkIikpICsKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBkYXRhID0gcGxvdERhdGEgJT4lCiAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKGlzT3V0bGllciA9PSAiUmV0YWluZWQiKSkgKwogICAgICBzY2FsZV95X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArCiAgICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiU3RlcCAjMjpcbk1lZGlhbiBBYnNvbHV0ZSBEZXZpYXRpb24iKSkgKwogICAgICB4bGFiKCJGMiAoYmFyaykiKSArCiAgICAgIHlsYWIoIkYxIChiYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEsCiAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpCiAgICAKIyBTdGVwIDM6IE1haGFsYW5ob2JpcyBEaXN0YW5jZSAtLS0tCiAgcGxvdERhdGEgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKFBpdGNoKSkgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgICAgRjJfbWFkID0gKGFicyhGMl9IeiAtIG1lZGlhbihGMl9IeikpLyBtYWQoRjJfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUpICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKEYxX21hZCA9PSBGQUxTRSAmIEYyX21hZCA9PSBGQUxTRSkgJT4lCiAgICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSwKICAgICAgICAgICAgICAgICAgaXNPdXRsaWVyID0gY2FzZV93aGVuKAogICAgICAgICAgICAgICAgICAgIG1EaXN0X3NkIDwgMiB+ICJSZXRhaW5lZCIsCiAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJSZW1vdmVkIgogICAgICAgICAgICAgICAgICApKQogICAgCiAgICBmNCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3REYXRhLAogICAgICAgICAgICAgICAgIGFlcyh4ID0gRjJfYiwKICAgICAgICAgICAgICAgICAgICAgeSA9IEYxX2IsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gaXNPdXRsaWVyKSkgKyAKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBkYXRhID0gcGxvdERhdGEgJT4lCiAgICAgICAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKGlzT3V0bGllciA9PSAiUmVtb3ZlZCIpKSArCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZGF0YSA9IHBsb3REYXRhICU+JQogICAgICAgICAgICAgZHBseXI6OmZpbHRlcihpc091dGxpZXIgPT0gIlJldGFpbmVkIikpICsKICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIlN0ZXAgIzM6XG5NYWhhbGFub2JpcyBEaXN0YW5jZSIpKSArIHhsYWIoIkYyIChiYXJrKSIpICsgeWxhYigiRjEgKGJhcmspIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSwKICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkKICAgIAojIEZpbmFsIEZvcm1hbnRzIC0tLS0KICAgIHBsb3REYXRhIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1EaXN0X3NkIDwgMikKICAgIAogICAgZjUgPC0gZ2dwbG90KGFlcyh4PUYyX2IsCiAgICAgICAgICAgICAgICAgICAgIHk9RjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHBsb3REYXRhLAogICAgICAgICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgY29sb3IgPSBteVBhbFsyXSkgKyAKICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiRmluYWwgRm9ybWFudCBWYWx1ZXMiKSkgKyB4bGFiKCJGMiAoYmFyaykiKSArIHlsYWIoIkYxIChiYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKICAgIAojIENvbWliaW5nIHBsb3RzCiAgICBmaWx0ZXJlZFBsb3QgPC0gZjEgKyBmMiArIGYzICsgZjQgKyBmNSArIHBhdGNod29yazo6Z3VpZGVfYXJlYSgpICsKICAgICAgcGF0Y2h3b3JrOjpwbG90X2xheW91dChndWlkZXMgPSAnY29sbGVjdCcsCiAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMykKICAgIGZpbHRlcmVkUGxvdAogICAgCiAgICBnZ3NhdmUocGxvdCA9IGZpbHRlcmVkUGxvdCwgIlBsb3RzL0ZpbHRlcmVkIEZvcm1hbnRzLnBuZyIsCiAgICAgICAgICAgaGVpZ2h0ID0gNiwKICAgICAgICAgICB3aWR0aCA9IDgsCiAgICAgICAgICAgdW5pdHMgPSAiaW4iLAogICAgICAgICAgIHNjYWxlID0gLjkpCiAgCmBgYAoKIyMgT1QgdnMuIFZBUwpgYGB7cn0KcGxvdERhdGFfSW50IDwtIEFjb3VzdGljRGF0YSAlPiUKICBkcGx5cjo6ZmlsdGVyKCFncmVwbCgiX3JlbCIsIFNwZWFrZXIpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoU3BlYWtlcikgJT4lCiAgZHBseXI6Om11dGF0ZShzZWdNaW4gPSBiYXNlOjptaW4oVkFTLCB0cmFuc0FjYyksCiAgICAgICAgICAgICAgICBzZWdNYXggPSBiYXNlOjptYXgoVkFTLCB0cmFuc0FjYyksCiAgICAgICAgICAgICAgICByYXRpbmdBdmcgPSBtZWFuKFZBUywgdHJhbnNBY2MsIG5hLnJtID0gVCksCiAgICAgICAgICAgICAgICBTcGVha2VyID0gYXMuZmFjdG9yKFNwZWFrZXIpLAogICAgICAgICAgICAgICAgRXRpb2xvZ3kgPSBhcy5mYWN0b3IoRXRpb2xvZ3kpKSAlPiUKICBhcnJhbmdlKHNlZ01heCkKCm15X3BhbCA8LSBjKCIjZjI2NDMwIiwgIiMyNzJEMkQiLCIjMjU2ZWZmIikKIyBXaXRoIGEgYml0IG1vcmUgc3R5bGUKcGxvdF9JbnQgPC0gZ2dwbG90KHBsb3REYXRhX0ludCkgKwogIGdlb21fc2VnbWVudChhZXMoeCA9IGZjdF9pbm9yZGVyKFNwZWFrZXIpLAogICAgICAgICAgICAgICAgICAgeGVuZCA9IFNwZWFrZXIsCiAgICAgICAgICAgICAgICAgICB5ID0gc2VnTWluLAogICAgICAgICAgICAgICAgICAgeWVuZCA9IHNlZ01heCwKICAgICAgICAgICAgICAgICAgIGNvbG9yID0gRXRpb2xvZ3kpKSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IFNwZWFrZXIsCiAgICAgICAgICAgICAgICAgeSA9IFZBUywKICAgICAgICAgICAgICAgICBjb2xvciA9IEV0aW9sb2d5KSwKICAgICAgICAgICAgICNjb2xvciA9IG15X3BhbFsxXSwKICAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICAgc2hhcGUgPSAxOSkgKwogIGdlb21fcG9pbnQoYWVzKHggPSBTcGVha2VyLAogICAgICAgICAgICAgICAgIHkgPSB0cmFuc0FjYywKICAgICAgICAgICAgICAgICBjb2xvciA9IEV0aW9sb2d5KSwKICAgICAgICAgICAgICNjb2xvciA9IG15X3BhbFsyXSwKICAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICAgc2hhcGUgPSAxNSkgKwogIGNvb3JkX2ZsaXAoKSsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgcGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICkgKwogIHhsYWIoIiIpICsKICB5bGFiKCJTcGVlY2ggSW50ZWxsaWdpYmlsaXR5IikgKwogIGdndGl0bGUoIlNwZWVjaCBJbnRlbGxpZ2liaWxpdHkiKSArCiAgeWxpbShjKDAsMTAwKSkKcGxvdF9JbnQKCm15UGFsIDwtIGMoIiMxQUFENzciLCAiIzEyNzlCNSIsICIjRkZCRjAwIiwgIiNGRDc4NTMiLCAiI0JGMzE3OCIpCm15U2hhcGVzIDwtIGMoMTYsIDE4LCAxNywgMTUpCgpzY2F0dGVyMSA8LSBnZ3Bsb3QocGxvdERhdGFfSW50LAogICAgICAgICAgICAgICAgICBhZXMoeCA9IFZBUywKICAgICAgICAgICAgICAgICAgICAgIHkgPSB0cmFuc0FjYywKICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gRXRpb2xvZ3ksCiAgICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IEV0aW9sb2d5LAogICAgICAgICAgICAgICAgICAgICAgbGluZXR5cGUgPSBFdGlvbG9neSkpICsKICBnZW9tX3BvaW50KCkgKwogICNnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYpICsKICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwxMDApLCB5bGltID0gYygwLDEwMCkpICsKICBsYWJzKHggPSAiSW50ZWxsaWdpYmlsaXR5IChWQVMpIiwgeSA9ICJJbnRlbGxpZ2liaWxpdHkgKE9UKSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gbXlTaGFwZXMpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKGFzcGVjdC5yYXRpbz0xLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiKQoKc2NhdHRlcjIgPC0gZ2dwbG90KHBsb3REYXRhX0ludCwKICAgICAgICAgICAgICAgICAgYWVzKHggPSBWQVMsCiAgICAgICAgICAgICAgICAgICAgICB5ID0gdHJhbnNBY2MsCiAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9IEV0aW9sb2d5LAogICAgICAgICAgICAgICAgICAgICAgc2hhcGUgPSBFdGlvbG9neSwKICAgICAgICAgICAgICAgICAgICAgIGxpbmV0eXBlID0gRXRpb2xvZ3kpKSArCiAgI2dlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsMTAwKSwgeWxpbSA9IGMoMCwxMDApKSArCiAgbGFicyh4ID0gIkludGVsbGlnaWJpbGl0eSAoVkFTKSIsIHkgPSAiSW50ZWxsaWdpYmlsaXR5IChPVCkiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15U2hhcGVzKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShhc3BlY3QucmF0aW89MSwKICAgICAgICBsZWdlbmQucG9zaXRpb249InJpZ2h0IikKCmNvbWJpbmVkU2NhdHRlciA8LSBnZ2FycmFuZ2Uoc2NhdHRlcjEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhdHRlcjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29tbW9uLmxlZ2VuZCA9IEYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbnJvdyA9IDEpCmNvbWJpbmVkU2NhdHRlcgoKZ2dzYXZlKGZpbGVuYW1lID0gIlBsb3RzL09UIGFuZCBWQVMgU2NhdHRlcnBsb3QucG5nIiwKICAgICAgIHBsb3QgPSBjb21iaW5lZFNjYXR0ZXIsCiAgICAgICBoZWlnaHQgPSAyLAogICAgICAgd2lkdGggPSA2LAogICAgICAgdW5pdHMgPSAiaW4iLAogICAgICAgc2NhbGUgPSAxKQoKcm0oc2NhdHRlcjEsIHNjYXR0ZXIyLCBjb21iaW5lZFNjYXR0ZXIpCmBgYAoKTW9kZWwgU2NhdHRlcnBsb3QKYGBge3J9Cm1vZGVsRmlndXJlRGF0YSA8LSBBY291c3RpY0RhdGEgJT4lCiAgZHBseXI6OmZpbHRlcighZ3JlcGwoIl9yZWwiLFNwZWFrZXIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KFNwZWFrZXIsIEV0aW9sb2d5LCBTZXgsIFZTQV9iLCB2b3dlbF9FRF9iLCBIdWxsX2IsIEh1bGxfYlZTRF8yNSwgSHVsbF9iVlNEXzc1LCBWQVMsIHRyYW5zQWNjKSAlPiUKICBkcGx5cjo6bXV0YXRlKFNwZWFrZXIgPSBhcy5mYWN0b3IoU3BlYWtlciksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IGFzLmZhY3RvcihFdGlvbG9neSksCiAgICAgICAgICAgICAgICBTZXggPSBhcy5mYWN0b3IoU2V4KSkgJT4lCiAgdGlkeXI6OnBpdm90X2xvbmdlcihjb2xzID0gVkFTOnRyYW5zQWNjLCBuYW1lc190byA9ICJJbnRUeXBlIiwgdmFsdWVzX3RvID0gIkludCIpICU+JQogIGRwbHlyOjptdXRhdGUoSW50VHlwZSA9IGNhc2Vfd2hlbigKICAgIEludFR5cGUgPT0gInRyYW5zQWNjIiB+ICJPVCIsCiAgICBUUlVFIH4gIlZBUyIKICApLAogICAgICAgICAgICAgICAgSW50VHlwZSA9IGFzLmZhY3RvcihJbnRUeXBlKSkKCnlsYWJlbCA8LSAiSW50ZWxsaWdpYmlsaXR5IgpteVBhbCA8LSBjKCIjMkQyRDM3IiwgIiMxMjc5QjUiKQpteVBhbFNoYXBlIDwtIGMoMTksIDEpCgpWU0EgPC0gbW9kZWxGaWd1cmVEYXRhICU+JQogIGdncGxvdCgpICsKICBhZXMoeCA9IFZTQV9iLAogICAgICB5ID0gSW50LAogICAgICBjb2xvciA9IEludFR5cGUsCiAgICAgIHNoYXBlID0gSW50VHlwZSwKICAgICAgbGluZXR5cGUgPSBJbnRUeXBlKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGZpbGwgPSAibGlnaHQgZ3JleSIpICsKICB4bGFiKGV4cHJlc3Npb24oIlZTQSAoQmFyayJeMioiKSIpKSArCiAgeWxhYih5bGFiZWwpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwxMDApKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBhc3BlY3QucmF0aW89MSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBteVBhbFNoYXBlKSArCiAgbGFicyhjb2xvcj0iSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgc2hhcGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiKQoKZGlzcCA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gdm93ZWxfRURfYiwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgeGxhYigiQ29ybmVyIERpc3BlcnNpb24gKEJhcmspIikgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gbXlQYWxTaGFwZSkgKwogIGxhYnMoY29sb3I9IkludGVsbGlnaWJpbGl0eSBUeXBlIiwKICAgICAgIHNoYXBlID0gIkludGVsbGlnaWJpbGl0eSBUeXBlIiwKICAgICAgIGxpbmV0eXBlID0gIkludGVsbGlnaWJpbGl0eSBUeXBlIikKCkh1bGwgPC0gbW9kZWxGaWd1cmVEYXRhICU+JQogIGdncGxvdCgpICsKICBhZXMoeCA9IEh1bGxfYiwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgeGxhYihleHByZXNzaW9uKCJWU0EiW0h1bGxdKiIgKEJhcmsiXjIqIikiKSkgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15UGFsU2hhcGUpICsKICBsYWJzKGNvbG9yPSJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBzaGFwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBsaW5ldHlwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIpCgp2c2QyNSA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gSHVsbF9iVlNEXzI1LAogICAgICB5ID0gSW50LAogICAgICBjb2xvciA9IEludFR5cGUsCiAgICAgIHNoYXBlID0gSW50VHlwZSwKICAgICAgbGluZXR5cGUgPSBJbnRUeXBlKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGZpbGwgPSAibGlnaHQgZ3JleSIpICsKICB4bGFiKGV4cHJlc3Npb24oIlZTRCJbMjVdKiIgKEJhcmsiXjIqIikiKSkgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15UGFsU2hhcGUpICsKICBsYWJzKGNvbG9yPSJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBzaGFwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBsaW5ldHlwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIpCgp2c2Q3NSA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gSHVsbF9iVlNEXzc1LAogICAgICB5ID0gSW50LAogICAgICBjb2xvciA9IEludFR5cGUsCiAgICAgIHNoYXBlID0gSW50VHlwZSwKICAgICAgbGluZXR5cGUgPSBJbnRUeXBlKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGZpbGwgPSAibGlnaHQgZ3JleSIpICsKICB4bGFiKGV4cHJlc3Npb24oIlZTRCJbNzVdKiIgKEJhcmsiXjIqIikiKSkgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15UGFsU2hhcGUpICsKICBsYWJzKGNvbG9yPSJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBzaGFwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBsaW5ldHlwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIpCgojIENyZWF0aW5nIE9UIFNjYXR0ZXJwbG90IEZpZ3VyZQoKc2NhdHRlciA8LSBWU0EgKyBkaXNwICsgcGF0Y2h3b3JrOjpndWlkZV9hcmVhKCkgKyBIdWxsICsgdnNkMjUgKyB2c2Q3NSArCiAgcGF0Y2h3b3JrOjpwbG90X2xheW91dChndWlkZXMgPSAnY29sbGVjdCcsCiAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMykKc2NhdHRlciAKCmdnc2F2ZSgiUGxvdHMvTW9kZWxGaWd1cmUucG5nIiwgc2NhdHRlciwKICAgICAgIGhlaWdodCA9IDQsCiAgICAgICB3aWR0aCA9IDYsCiAgICAgICB1bml0cyA9ICJpbiIsCiAgICAgICBzY2FsZSA9IDEuMSkKYGBgCgojIExpc3RlbmVyIERlbW9ncmFwaGljIEluZm9ybWF0aW9uCmBgYHtyfQoKTGlzdGVuZXJEZW1vIDwtIExpc3RlbmVycyAlPiUKICBmdXJuaXR1cmU6OnRhYmxlMShhZ2UsIGdlbmRlciwgcmFjZSwgZXRobmljaXR5KQoKTGlzdGVuZXJEZW1vCgpgYGAKCiMgU3BlYWtlciBEZW1vZ3JhcGhpY3MKCmBgYHtyfQoKU3BlYWtlckRlbW8gPC0gQWNvdXN0aWNEYXRhICU+JQogIGRwbHlyOjpzZWxlY3QoYyhTcGVha2VyLCBTZXgsIEV0aW9sb2d5KSkKCkFnZXMgPC0gcmlvOjppbXBvcnQoIlByZXBwZWQgRGF0YS9TcGVha2VyIEFnZXMueGxzeCIpCgpTcGVha2VyRGVtbyA8LSBmdWxsX2pvaW4oU3BlYWtlckRlbW8sIEFnZXMsIGJ5ID0gIlNwZWFrZXIiKQoKU3BlYWtlckRlbW9JbmZvIDwtIFNwZWFrZXJEZW1vICU+JQogIGZ1cm5pdHVyZTo6dGFibGUxKFNleCwgRXRpb2xvZ3ksIEFnZSwgbmEucm0gPSBGKQoKU3BlYWtlckRlbW9JbmZvCgpTcGVha2VyRGVtbyAlPiUKICBkcGx5cjo6c3VtbWFyaXplKG1lYW5fYWdlID0gbWVhbihBZ2UsIG5hLnJtID0gVCksIGFnZV9zZCA9IHNkKEFnZSwgbmEucm0gPSBUKSwgYWdlX3JhbmdlID0gcmFuZ2UoQWdlLCBuYS5ybSA9IFQpKQoKYGBgCgo=